如何让fork()' ed孩子共享stdin?

时间:2017-04-07 15:10:56

标签: c pipe fork stdin dup

我有这个小程序:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/wait.h>

int main() {
    int orig = 1;
    for (int i = 0; (i != 3) && orig; ++i) {
        orig = orig && fork();
    }
    if (orig) {
        for (int i = 0; i != 3; ++i) {
            wait(NULL);
        }
    } else {
        int num;
        scanf("%d", &num);
        printf("%d\n", num*num);
    }
}

它应该简单地对从stdin读取的三个数字进行平方,但它不能按预期工作。具体来说,它看起来像一个孩子&#34; hogs&#34;所有cat输入,因为程序大致如此:

2
2
2

4
0
0

我想我需要使用dup来解决这个问题,但在我们的课程资料中几乎没有任何内容,我在网上找到的所有东西都太复杂了,我无法理解。我如何才能让所有流程共享stdin

2 个答案:

答案 0 :(得分:0)

只有一个子进程从stdin读取并清空文件输入缓冲区,它不会自动发送给所有子进程。 有关类似情况,请参阅Reading from stdin by multiple processes;请注意,scanf也使用FILE *缓冲输入,所以结论是一样的。

应该是父母一个接一个地读取然后将输入数据发送给所有孩子。

答案 1 :(得分:0)

  

如何让fork()&#39; ed孩子共享stdin?

除非你做出规定以避免它,否则孩子分享stdin。但是他们共享本身,这只是字节的管道。传输流的数据不是流的一部分。

  

具体来说,它看起来像一个孩子&#34; hogs&#34;所有被忽略的输入,

是。这种具体行为并不能得到保证,但这似乎是合情合理的。只有一个进程可以读取每个字节 - 从流中删除字节,以便其他进程不可用。缓冲和分叉的相互作用有一些细节,在某些情况下可能会产生不同的行为,但避免这些并发症很重要。

您需要不同的沟通模式。以下是一些更合理的选择:

  • 预读。原始进程从流中读取所有需要的数据并将其记录在内存中。每个fork() ed子项都会继承要使用的数据副本。

  • 输入多路复用。它设置的主要过程或其他过程负责读取标准输入。它通过管道将其读取的内容转发给每个其他进程(三个原始孩子各一个)

  • 输入总线。子进程通过管道连接在一起(如果需要,可以在其标准流上设置);无论他们阅读什么数据,除了执行他们的正常工作外,他们还会向管道上的下一个孩子转发。