1 管道pipe使用兄弟进程通信实现ls | wc –l
案例3,使用管道实现兄弟进程间通信。 兄:ls 弟: wc -l 父:等待回收子进程。要求,使用“循环创建N个子进程”模型创建兄弟进程,使用循环因子i标示。注意管道读写行为。
1.1 首先先看错误的并且大家很容易犯的错误代码。
#include <stdio.h>
#include <unistd.h>
#include <sys/wait.h>
int main(void)
{
pid_t pid;
int fd[2], i;
int ret = pipe(fd);
if (ret == -1) {
perror("pipe error:");
exit(1);
}
for (i = 0; i < 2; i++) {
pid = fork();
if(pid == -1) {
perror("fork error:");
}else if(pid == 0){
break;
}
}
if (i == 2) {
for(i = 0; i < 2; i++){//两个儿子wait两次
wait(NULL
}
} else if (i == 0){//兄
close(fd[0]);
dup2(fd[1], STDOUT_FILENO);
execlp("ls", "ls", NULL);
perror("execlp error in xiong.");
} else if (i == 1){//弟
close(fd[1]);
dup2(fd[0], STDIN_FILENO);
execlp("wc", "wc", "-l", NULL);
perror("execlp error in didi.");
}
return 0;
}
上面的程序看似没有任何问题,但实际上是会卡死,看图。程序类似卡死了的状态。
下面我们画图分析,注意在写多进程的代码时,若有错误,最好画图分析,非常方便易懂。
1.2 画图分析上面的程序
看下图。
- 1)首先父进程先调用pipe函数创建了一个管道,指向w,r两端。
- 2)然后fork了两个子进程,同样指向了父进程的w,r两端。
- 3)然后兄进程关闭了读端,弟进程关闭了写端,但是这样的话,父进程的读写两端还没有关闭,导致管道无法单向流动,造成类似卡死的状态。
- 4)所以解决就是将父进程的读写端关闭即可。
1.3 正确代码
#include <stdio.h>
#include <unistd.h>
#include <sys/wait.h>
int main(void)
{
pid_t pid;
int fd[2], i;
int ret = pipe(fd);
if (ret == -1) {
perror("pipe error:");
exit(1);
}
for (i = 0; i < 2; i++) {
pid = fork();
if(pid == -1) {
perror("fork error:");
}else if(pid == 0){
break;
}
}
if (i == 2) {
close(fd[0]);
close(fd[1]);
for(i = 0; i < 2; i++){//两个儿子wait两次
wait(NULL
}
} else if (i == 0){//兄
close(fd[0]);
dup2(fd[1], STDOUT_FILENO);
execlp("ls", "ls", NULL);
perror("execlp error in xiong.");
} else if (i == 1){//弟
close(fd[1]);
dup2(fd[0], STDIN_FILENO);
execlp("wc", "wc", "-l", NULL);
perror("execlp error in didi.");
}
return 0;
}
程序成功执行了。
```![在这里插入图片描述](https://img-blog.csdnimg.cn/20210110121119813.png)