【发布时间】:2022-01-13 02:55:08
【问题描述】:
我目前在以下练习中遇到问题:
我想用下面的程序在 linux bash 中“模仿”管道命令行ls | wc。
我要做的是:
- 创建管道
- 创建一个 reader child 和 writer child
- 作家子关闭管道的读取端并将其标准输出重定向到管道的写入端
- reader child 关闭管道的写入端并将管道的读取端作为标准输入
- 两个孩子都执行 exec,编写器执行
ls程序,将输出通过管道传递给读取器,读取器在该输出上执行wc程序。
当我在 linux 终端中执行 ls | wc 时,我得到以下结果:
8 8 101
但是如果我执行我的程序,我会得到以下结果:
0 0 0
这是我的程序:
#include <stdlib.h>
#include <errno.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>
#include <sys/wait.h>
#include <libgen.h>
#include <signal.h>
#include <errno.h>
int main(void){
int mypipe[2];
pid_t pid1, pid2;
if (pipe(mypipe)<0)
perror ("pipe error"), exit(1);
if ((pid1=fork())<0)
perror ("fork error"), exit(1);
else if (pid1==0) {
//reader child
close (mypipe[1]);
if (dup2(mypipe[0], STDIN_FILENO)!=STDIN_FILENO)
perror ("dup2 error"), exit(1);
close (mypipe[0]);
if (execlp("wc", "wc", NULL)<0)
perror("execlp1 error"), exit(1);
else { //pid >0, parent
if ((pid2=fork())<0)
perror ("fork error"), exit(2);
else if (pid2==0) {
//writer child
close(mypipe[0]);
if (dup2(mypipe[1], STDOUT_FILENO) != STDOUT_FILENO)
perror("dup2 error"), exit(1);
close (mypipe[1]);
if (execlp("ls", "ls", NULL)<0)
perror ("execlp error"), exit(1);
}
else { //parent
close(mypipe[0]);
close(mypipe[1]);
waitpid(pid1, NULL, 0);
waitpid(pid2, NULL, 0);
exit(0);
}
}
}
return 0;
}
我做错了什么?提前感谢您的回答!
【问题讨论】:
-
请注意,如果
execlp()(或任何其他exec*()函数)成功,它不会返回;如果返回,则失败。无需测试返回值。虽然在这种情况下它可能无关紧要,但通常最好在打印错误后发送exit()或_exit()。 -
if (execlp("wc", "wc", NULL)<0)当execlp成功时,该行之后的所有内容都不会运行。但是你在if的else中有第二个fork。代码缩进应该提醒你这样做。那不是你想要的。您需要将else { //pid >0, parent与else if (pid1==0)配对。