I'm new to piping and have been trying to create a pair of pipes which allow a child process to write to the parent process, and the parent process to communicate back. There is 1 parent with up to 4 children. The child becomes a different program with exec.
What I have working:
Writing from the parent to the child process. When I read in the child program's stdin, it will receive what I wrote from the parent.
The aim:
To create a card game where the parent talks to each individual client (the child processes) and gives all the moves and information to them, from its stdout to the children's stdin. The individual child processes give back their moves on their stdout, read by the main parent. The moves that the game makes is fully decided by a sequence, not players. So it's a bot game.
What I am stuck with:
I'm not sure how to get it so the parent can read the child's stdout through a file stream. When I try to setup the reading from child lines, the code seems to stop working. Not even the child can read from parent (it seems to stop at the now commented out liens for setting up child to parent).
I also am unsure how to "wait" until something appears. Like, at the start the players have to send a "ready" message back to the parent to let them know they are working. Once I send the "ready" from the child, how do I "wait" indefinitely until the next message appears?
I'm not sure if I'm setting up the pipes correctly. Can someone provide guidance on how to use communication pipes and confirm my logic below?
What I gather for getting parent to write to child is:
- Create the pipe first
- Fork off the parent process into another process (child)
- Connect the pipe's in to the parent's stdout, and close off the reading side for the parent using dup2 and close
- Connect the pipe's out to the child's stdin, and close off the writing part for the child using dup2 and close
- Get a file stream using fdopen() from the file descriptor and then print to that.
- The child process stdin is now whatever you print to stdout from the parent.
Is this correct? I tried applying this kind of logic for child to parent but reversing it.
- Connect the in pipe to the read file stream, which is where the child program writes to from its stdout.
Connect the out pipe to the read stream, where the parent reads from.
void start_child_process(Game *game, int position) { int child2Parent[2]; int parent2Child[2]; if (pipe(parent2Child)) { printf("PIPE FAIL!\n"); } if (pipe(child2Parent)) { printf("PIPE FAIL!\n"); } pid_t pid = fork(); game->readStream[position] = fdopen(child2Parent[0], "r"); game->writeStream[position] = fdopen(parent2Child[1], "w"); if (pid) { // Parent // Write from parent to child close(parent2Child[0]); dup2(fileno(game->writeStream[position]), STDOUT_FILENO); fprintf(game->writeStream[position], "%s", "test message"); fflush(game->writeStream[position]); close(parent2Child[1]); // Read from child -- not working /*dup2(child2Parent[0], STDIN_FILENO); close(child2Parent[0]); close(child2Parent[1]); */ } else { // Setup child to read from stdin from parent dup2(parent2Child[0], STDIN_FILENO); close(parent2Child[1]); // Setup writing from child to parent /* if (dup2(child2Parent[1], STDOUT_FILENO) == -1) { fprintf(stderr, "dup2 in child failed\n"); } else { fprintf(stderr, "dup2 in child successful\n"); close(child2Parent[0]); close(child2Parent[1]); } */ if ((int)execl("child", "2", "A", NULL) == -1) { printf("Failed child process\n"); } } }
My child main has the following which reads it:
char string[100];
printf("reading from pipe: %s\n", fgets(string, 100, stdin));
But I'm not sure how
Also, I'm not permitted to use popen() or write(). I'm also encouraged to use file streams apparently.