0

I have this small program:

#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);
    }
}

Which is supposed to simply square three numbers that it reads from stdin, but it does not work as expected. Specifically, it looks like one of the children "hogs" all of the catted input, since the program does roughly this:

2
2
2

to

4
0
0

I think I need to use dup to fix this, but there is almost nothing on it in our course materials, and all I find on the web is way too complicated for me to understand. How exactly can I make all the processes share stdin?

Akiiino
  • 1,050
  • 1
  • 10
  • 28

2 Answers2

0

Only one child process reads from stdin and empties the file input buffer, it is not automatically sent to ALL children. See Reading from stdin by multiple processes for a similar scenario; please note that scanf also uses FILE* buffered input, so the conclusion is the same.

It should be the parent that reads and then sends the input data to all the children, one by one.

Community
  • 1
  • 1
0

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

Unless you make provisions to avoid it, the children do share stdin. But they share the stream itself, which is just a conduit for bytes. The data transiting the stream are not part of the stream.

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

Yes. That specific behavior is not guaranteed, but it is plausible and in fact likely. Only one process can read each byte -- that removes the byte from the stream, so that it is unavailable to other processes. There are some fine details around the interaction of buffering and forking that might under some circumstances produce an appearance of different behavior, but avoiding such complications is important.

You need a different communication pattern. Here are some of the more plausible alternatives:

  • Pre-reading. The original process reads all the needed data from the stream and records it in memory. Each fork()ed child inherits a copy of the data to work with.

  • Input multiplexing. The main process or an additional process it sets up takes responsibility for reading stdin. It forwards whatever it reads to each of the other processes via pipes (one per each of the three original children)

  • Input bus. The child processes are connected together via pipes (which can be set up on their standard streams if desired); whatever data they read they also forward to the next child over the pipe, in addition to performing their regular work.

John Bollinger
  • 160,171
  • 8
  • 81
  • 157