分叉管道子流程

时间:2012-07-19 20:17:57

标签: c exec fork

分叉管道子流程的最佳技术是什么?

我当前的程序需要运行另一个进程,实际上是一些由管道链接的命令。我不需要知道命令的输出,只要它们失败或成功,所以我使用fork / exec。

命令行中的等效项将是

 /path/to/A arg1 arg2 | /path/to/B argB1 | /path/to/C

注意:使用脚本是不实际的,因为A / B / C将来可能会发生变化。

我使用的两种技术是:

  1. 递归前叉。在下一个分支中连接父级(输入到其父级)可用于子级的输出。

  2. 在顶层创建所有管道 然后使用循环来分叉所有可以正确连接管道的子项。

2 个答案:

答案 0 :(得分:1)

不要递归地分叉。使B成为A的子过程并不是一个好主意。例如,如果B调用setsid在其自己的会话中运行,则它将使用不相关的A。如果B死了,A会得到一个SIGCHILD,而不是你。特别是,您将无法获得B的返回状态。

这是在一系列管道上分叉n个子代码的草图。警告:我直接在浏览器中输入了代码;可能有很多错别字,我省略了所有错误检查。

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 */

答案 1 :(得分:0)

如果您使用的是unix,那么简单system("/path/to/A arg1 arg2 | /path/to/B argB1 | /path/to/C")就可以执行您想要的操作。它调用shell作为/bin/sh -c $STRING_PASSED_TO_SYSTEM。如果您想要更精细的控制,例如读取输出或写入输入的能力,请考虑C库中的popen()例程。