父进程创建两个子进程,父子进程之间利用管道进行通信。要求能显示父进程、子进程各自的信息,体现通信效果。(源程序pipe_1.c)
一开始,我忘了初始化pipe,很傻*的直接把fd当管道使,出现了儿子喊爸爸"i am your father."的笑话。
后面我意识到,原来是我pipe忘了初始化了。
然后改成了上面的代码,结果发现程序一直卡在这一步
后面用AI才知道,原来是pipe写的位置错了,应该写在fork的前面,否则会导致父子进程各有一个匿名管道,从而导致进程卡死。
回顾一下匿名管道的特性:
1.读写分开。
2.无名,只能在同一根进程间可以使用。
3.不保证数据写入的原子性。即当父子进程同时向管道写入数据时,有可能会导致写入的数据被破坏。比如同时传入hello,有可能读取到的会是hehellollo。因此无名管道只能进行1v1通信
[写者:有权限可以对管道进行写入操作;读者:有权限可以对管道进行读取操作]
由于管道本身可以初始化自带数据,所以不一定需要写者,但一定需要有读者,否则会报错pipe borken
这个是修改后正确的代码
#include<stdlib.h>
#include<stdbool.h>
#include<unistd.h>
#include<strings.h>
#include<stdio.h>
#include<sys/wait.h>
#include<string.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<errno.h>
#include<fcntl.h>
int main()
{int fd[2],pid;pipe(fd);while((pid=fork())==-1); //若程序没有生成子进程,则重复执行if(pid>0) //父进程{printf("i am parent.\n");char f_r[50];bzero (f_r ,50); //清空字符串read(fd[0],f_r,50);printf("chiled said: %s\n",f_r);char f_said[50]="i am your father.";write(fd[1],f_said,strlen(f_said));}else if(pid==0){printf("i am child.\n");char c_said[50]="hi,dad.";write(fd[1],c_said,strlen(c_said));sleep(3);char c_r[50];bzero(c_r,50);read(fd[0],c_r,50);printf("dad said: %s\n",c_r);}return 0;
}
这是运行结果
可能有人要问了,为什么最后一句的前面有shell会话命令头呢?
这是因为会话只于程序的父进程绑定,当父进程结束时,shell会以为进程已经执行结束,所以会弹出命令头。
在子进程中,若使用了exec函数,则会将原函数代码全部替换为exec参数文件代码,并从头执行,所以原来exec下面的代码无法执行。
若执行了原来exec下面的代码,则说明exec没有正确执行。