Reputation: 264381
What is the best technique to fork a pipe-lined sub processes?
My current program needs to run another processes that is actually a couple of commands linked by pipes. I do not need to know the output of the commands just if they fail or succeed so I am using fork/exec.
The equivalent on the command line would be
/path/to/A arg1 arg2 | /path/to/B argB1 | /path/to/C
Note: Using a script is not practical as it A/B/C may change in the future.
The two techniques I though of are:
Recursive fork. Connect the parent (input to its parent) output available for child in next fork.
Create all pipes at top level.
Then use a loop to fork all children that can then connect the pipes appropriately.
Upvotes: 3
Views: 346
Reputation: 107759
Don't fork recursively. Making B a subprocess of A is not a good idea. For example, if B calls setsid
to run in its own session, it would take the unrelated A with it. If B dies, A would get a SIGCHILD, not you. In particular, you would not be able to obtain the return status of B.
Here's a sketch of the code to fork n children on a series of pipes. Warning: I typed the code directly into my browser; there are probably many typos, and I omitted all error checks.
char *executables[n];
char *args[n];
int pipes[2*n+2]; /* child i reads from */
int child_pids[n];
int ret; /*Error checking omitted; abort if ret ever becomes negative*/
ret = pipe(pipes);
for (i = 0; i < n; i++) {
ret = pipe(pipes + 2 * i + 2);
ret = fork();
if (ret == 0) {
/* Code of child i */
close(pipes[2*i+1]);
close(pipes[2*i+2]);
dup2(pipes[2*i], 0);
dup2(pipes[2*i+3], 1);
ret = execv(executables[i], args[i]);
}
close(pipes[2*i]);
close(pipes[2*i+3]);
child_pids[i] = ret;
}
/* interact with the subprocesses, then call wait or waitpid as needed */
Upvotes: 1
Reputation: 12033
If you're on a unix, a simple system("/path/to/A arg1 arg2 | /path/to/B argB1 | /path/to/C")
will do what you want. It invokes a shell as /bin/sh -c $STRING_PASSED_TO_SYSTEM
. If you want finer control, for example the ability to read the output or write to the input, consider the popen()
routine in the C library.
Upvotes: 0