显示的代码几乎可以工作(它减少了一些角落,但它可以工作),因为分叉的子进程确保执行的进程将写入的文件描述符(在这种情况下)ls
)并从中读取(在情况下wc
) 是管道的适当末端。您无需再做任何事情;标准输入是文件描述符0,所以wc
不带(文件名)参数从标准输入读取。ls
始终写入标准输出,文件描述符 1,除非正在写入错误消息。
代码片段中共有三个流程;父进程和两个子进程,每个子进程一个fork()
。
父进程也应该关闭管道的两端;它只关闭一个。
一般来说,当你做了一个dup()
or dup2()
调用管道文件描述符时,您应该关闭管道的两端。你在这里可以逃脱惩罚,因为ls
生成数据并终止;你不会在所有情况下都这样做。
评论:
/* Set stdout to the input side of the pipe, and run 'ls'. */
不准确;你正在设置stdout
到管道的输出侧,而不是输入侧。
您应该在执行后出现错误退出execv()
来电;如果他们失败了,他们就会返回,并且这个过程可能会造成严重破坏(例如,如果ls
失败,你最终会得到两个副本wc
跑步。
An SSCCE http://sscce.org/
注意在每个过程中小心关闭管道的两端。一旦启动了两个子进程,父进程就不再使用管道。我留下了关闭的代码filedes[1]
很早就到位(但将其从明确的else
块,因为以下代码也仅在以下情况下执行:else
被处决)。我很可能保留了一对closes()
在需要关闭文件的三个代码路径中的每一个中。
#include <stdio.h>
#include <stdlib.h>
#include <sys/wait.h>
#include <unistd.h>
int main(void)
{
int filedes[2];
int corpse;
int status;
pipe(filedes);
/* Run LS. */
pid_t pid = fork();
if (pid == 0)
{
/* Set stdout to the output side of the pipe, and run 'ls'. */
dup2(filedes[1], 1);
close(filedes[1]);
close(filedes[0]);
char *argv[] = {"ls", NULL};
execv("/bin/ls", argv);
fprintf(stderr, "Failed to execute /bin/ls\n");
exit(1);
}
/* Close the input side of the pipe, to prevent it staying open. */
close(filedes[1]);
/* Run WC. */
pid = fork();
if (pid == 0)
{
/* Set stdin to the input side of the pipe, and run 'wc'. */
dup2(filedes[0], 0);
close(filedes[0]);
char *argv[] = {"wc", NULL};
execv("/usr/bin/wc", argv);
fprintf(stderr, "Failed to execute /usr/bin/wc\n");
exit(1);
}
close(filedes[0]);
while ((corpse = waitpid(-1, &status, 0)) > 0)
printf("PID %d died 0x%.4X\n", corpse, status);
return(0);
}
输出示例:
$ ./pipes-14312939
32 32 389
PID 75954 died 0x0000
PID 75955 died 0x0000
$