如何让'fork()'ed children 共享标准输入?

How can I make 'fork()'ed children share stdin?

我有这个小程序:

#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 读取的三个数字进行平方,但它没有按预期工作。具体来说,它看起来像 children "hogs" 所有 catted 输入之一,因为程序大致是这样的:

2
2
2

4
0
0

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

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

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

How can I make 'fork()'ed children share stdin?

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

Specifically, it looks like one of the children "hogs" all of the catted input,

是的。不能保证这种特定行为,但它是合理的,而且实际上是可能的。只有一个进程可以读取每个字节——从流中删除该字节,以便其他进程无法使用它。关于缓冲和分叉的交互有一些细节,在某些情况下可能会产生不同的行为,但避免这种复杂化很重要。

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

  • Pre-reading。原始进程从流中读取所有需要的数据并将其记录在内存中。每个 fork()ed child 都会继承一份要使用的数据。

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

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