刷新管道的缓冲区

时间:2016-08-04 15:47:04

标签: c pipe

我正在玩管道,并从here获取以下代码;一旦我理解我正在目睹一个块缓冲问题,我添加了一个原始代码中没有的sleep()调用:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

int main ()
{
    FILE *ps_pipe;
    FILE *grep_pipe;

    int bytes_read;
    int nbytes = 100;
    char *my_string;

    char buffer[100];

    /* Open our two pipes */
    ps_pipe = popen ("ls", "r");
    grep_pipe = popen ("sort", "w");

    /* Check that pipes are non-null, therefore open */
    if ((!ps_pipe) || (!grep_pipe))
    {
      fprintf (stderr,
               "One or both pipes failed.\n");
      return EXIT_FAILURE;
    }

    bytes_read = 0; 
    while (fgets(buffer, sizeof(buffer), ps_pipe)) 
    { 
        fprintf(grep_pipe, "%s", buffer);
        bytes_read += strlen(buffer); 
    } 

    printf("Total bytes read = %d\n", bytes_read); 
    sleep(2);

    /* Close ps_pipe, checking for errors */ 
    if (pclose(ps_pipe) != 0) 
    { 
        fprintf(stderr, "Could not run 'ps', or other error.\n"); 
    } 

    /* Close grep_pipe, cehcking for errors */ 
    if (pclose(grep_pipe) != 0) 
    { 
        fprintf(stderr, "Could not run 'grep', or other error.\n"); 
    } /* Exit! */ 

    return 0; 
} 

编辑[这是错误的,请参阅下面的答案]:这样,我确保一旦编程从其主函数返回,管道的缓冲区就会被刷新。

但是,我仍然不明白原因:为什么管道的内核缓冲区会被刷新到stdout?前者与后者有什么关系? [编辑:这也是错误的,但留待上下文]

1 个答案:

答案 0 :(得分:2)

睡眠对任何内核缓冲区都没有影响。

您在stdout上看到的输出来自sort进程,并通过关闭grep_pipe来触发。

您的程序实际上是在模拟以下shell脚本:

ls | sort

您打开管道以从ls读取,使用其所有输出(来自其stdout)并将此输出发送到stdin进程的sortsort无法对行进行排序,直到它包含所有行,并且只有在stdin关闭时才知道它包含所有行,这在关闭grep_pipe时会发生

关闭grep_pipe后,sort会发挥作用,生成排序后的行stdoutpclose在相关进程终止之前不会返回,此时sort将完成所有输出的生成。