如果构建重定向链,这本质上就是 shell 所做的事情,即类似于
ls | grep foo | sort | uniq
有一些关于Unix编程的优秀介绍文本,其中通过书中实现了一个简单的shell。 shell 的任务之一就是重定向。其中一本是 Michael K. Johnson 和 Erik W. Troan 所著的《Linux 应用程序编程》。
本书的主页:http://ladweb.net/ http://ladweb.net/
要为 N 个进程构建重定向链,您需要 N-1 个管道。对于每个重定向,您使用以下命令创建一个管道pipe(int fds[2])
系统调用。后fork()
ing,但之前execv
ing use dup2(int from, int to)
将管道的末端“连接”到每个进程的标准输入 (0) 或标准输出。这是一个过于简化的代码,没有错误检查:
int pipe_A[2];
int pipe_B[2];
pipe(pipe_A);
pipe(pipe_B);
pid_t pid_A, pid_B, pid_C;
if( !(pid_A = fork()) ) {
dup2(pipe_A[1], 1); /* redirect standard output to pipe_A write end */
execv(...);
}
if( !(pid_B = fork()) ) {
dup2(pipe_A[0], 0); /* redirect standard input to pipe_A read end */
dup2(pipe_B[1], 1); /* redirect standard output to pipe_B write end */
execv(...);
}
if( !(pid_C = fork()) ) {
dup2(pipe_B[0], 0); /* redirect standard input to pipe_B read end */
execv(...);
}
请注意,管道的数组索引的选择方式反映了标准输入/输出文件描述符(如果它们用于 stdio 重定向)。这个选择并不是任意的。
当然,您可以将管道连接到任何文件描述符(例如,有一些应用程序期望其父级打开,例如连接到管道的 fd 3 和 4),并且大多数 shell 也直接支持这一点(例如 1>&3 将重定向标准输出到 fd 3)。然而数组索引pipe(int fds[2])
当然是0和1。我只是这么说,因为我有一些货物崇拜编程的学生,他们无意中也将目标 fd 也用于管道系统调用数组。
等待所有孩子使用完毕waitpid(-1, NULL, 0)
– 我认为这就是我预先回答者的意思,这意味着:等待所有子进程完成。另一种选择是打电话wait()
在一个循环中,它将返回刚刚终止的子进程的 pid。如果再次调用并且仍然有一个孩子在运行,它将再次阻塞。如果没有孩子,则返回-1;我更喜欢waitpid
解决方案。