定期写入由C中的子进程读取的管道

时间:2018-01-13 21:31:55

标签: c pipe fork sleep

我写了下面的代码。父进程write一次只能有一个字符,然后是sleep个调用。子进程read一次一个字节,并在读取后立即打印。

然而,当我运行它时,等待几秒后我立刻得到所有输出。我希望每秒能得到一个角色。这是为什么?

(我知道我可以一次性写出字符串,但这是未来的实验。)

int fd[2];
pipe(fd);

pid_t pid = fork();
if (pid == 0) {
    close(fd[WRITE_END]);
    char *read_msg;
    printf("Read: ");

    // Read characters.
    while (read(fd[READ_END], read_msg, 1)) {
        printf("%c", *read_msg);
    }

    printf("\n");
    close(fd[READ_END]);
} else {
    close(fd[READ_END]);
    char *msg = "Hello!";
    char *c = msg;

    // Write a character from parent every second.
    while (*c) {
        write(fd[WRITE_END], c++, 1);
        sleep(1);
    }

    close(fd[WRITE_END]);
    wait();
}

2 个答案:

答案 0 :(得分:1)

您正在使用printf打印接收字符。 printf将数据写入FILE对象,代表缓冲区文件。由于性能原因,它会避免将数据写入实际文件,直到满足某些条件(或收集到足够的数据)。如果可以刷新数据,请在此处描述:http://en.cppreference.com/w/cpp/io/c/setvbuf

您的程序输出最有可能是#line;缓冲",因此数据实际上会在每个新行字符上写入终端。

为避免这种情况,您希望使用fflush在每个收到的字符后手动刷新数据。另一种方法是使用setvbuf更改缓冲策略。

你想要这样的东西:

char c;
while (read(fd[READ_END], &c, 1) > 0) {
    printf("%c", c);
    fflush(stdout);
}

请注意,您还应该将数据读入char对象。

答案 1 :(得分:1)

printf默认使用缓冲文件,它会自动刷新'\ n'或者如果你打电话 fflush(stdout);

所以只需在你的循环阅读后冲洗。