Redirect stdout of two processes to another process's stdin in Linux C
c, linux, redirect, stdin, stdout
Solution
I'm not sure that it's a good idea, but it is perfectly feasible. The key observation is that you only need one pipe. Several processes (with a common parent) can write to a single pipe. However, only one file descriptor can be used as the standard input. In the original code, only one of the pipes was connected to C as its standard input (the others were still connected, but mainly because you hadn't closed enough descriptors).
- Rule of thumb: if you connect one end of a pipe to standard input or standard output via `dup2()` (or `dup()`), you should close both of the file descriptors returned by `pipe()`.
Try this code for size. I've reduced the bushiness of the tree, removed unused variables (nothing uses the process IDs returned by `fork()`), renamed the pipe, made sure it is closed properly in each process, and provided some writing activity in processes A and B and some reading activity in process C in lieu of running commands. I'm assuming that `usleep()` (micro-sleep, sleep time expressed in microseconds) is available; if not, try `nanosleep()`, but it has a more complex interface).
#include <unistd.h>
int main(void)
{
int ABtoC[2];
pipe(ABtoC);
if (fork() > 0)
{
// Process A
close(ABtoC[0]);
dup2(ABtoC[1], STDOUT_FILENO);
close(ABtoC[1]); // Close this too!
// Process A writing to C
for (int i = 0; i < 100; i++)
{
write(STDOUT_FILENO, "Hi\n", sizeof("Hi\n")-1);
usleep(5000);
}
}
else if (fork() > 0)
{
// Process B
close(ABtoC[0]);
dup2(ABtoC[1], STDOUT_FILENO);
close(ABtoC[1]);
// Process B writing to C
for (int i = 0; i < 100; i++)
{
write(STDOUT_FILENO, "Lo\n", sizeof("Lo\n")-1);
usleep(5000);
}
}
else
{
char buffer[100];
ssize_t nbytes;
close(ABtoC[1]);
dup2(ABtoC[0], STDIN_FILENO);
close(ABtoC[0]);
// Process C reading from both A and B
while ((nbytes = read(STDIN_FILENO, buffer, sizeof(buffer))) > 0)
write(STDOUT_FILENO, buffer, nbytes);
}
return(0);
}
The tail end of a run on my Mac (Mac OS X 10.7.5, GCC 4.7.1) produced:
Lo
Hi
Lo
Hi
Lo
Hi
Lo
Hi
Lo
Hi
Hi
Lo
Lo
Hi
Hi
Lo
Hi
Lo
Hi
Lo
Hi
Lo
Hi
Lo
Lo
Hi
Problem
I'm running into problem about redirect stdout of multi process. Assuming I have process A, I use fork() in A and then I get process A and B. And I use fork() in B, finally I get process A, B and C. Both B and C are implementing other program by exec(). Now, I try to redirect the stdout of A and B to stdin of C with two pipes. ``` #include<unistd.h> #include<stdio.h> #include<sty/types.h> int main() { int AtoC [2]; pipe(AtoC); int fd1,fd2; fd1=fork(); if(fd1>0) { /***In process A, I do the following steps: ***/ close(AtoC[0]); dup2(AtoC[1], STDOUT_FILENO); /* program running in process A */ } else { int BtoC [2]; pipe(BtoC); fd2=fork(); if(fd2>0) { /***In process B, I do the following steps: ***/ close(AtoC[1]); close(BtoC[0]); dup2(BtoC[1], STDOUT_FILENO); /*** execute another program in process B using execl(); ***/ } else { /*** In process C, I do the following steps: ***/ close(AtoC[1]); close(BtoC[1]); dup2(AtoC[0],STDIN_FILENO); dup2(BtoC[0],STDIN_FILENO); /*** execute another different program in process C using execl(); ***/ } } } ``` Now, after these two statements : ``` dup2(AtoC[0],STDIN_FILENO); dup2(BtoC[0],STDIN_FILENO); ``` the stdin of process C is finally redirect to `BtoC[0]` ,which is the stdout of process B. And the stdout of process A is not passed into process C's stdin. My question is whether there is any solution can let me redirect both process A and B's stdout into process C's stdin at the same time. Another question is if I also want to print the stdout of process A in screen, what should I do? I know the command `tee` in command line. I try to use the corresponding function `tee(int fd_in, int fd_out, size_t len, unsigned int flags)`in process A, but I failed to print anything of stdout of process A. Any suggestion is appreciated, thanks.