实验4 进程的管道通信
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
实验4 进程的管道通信
一、实验目的
1)加深对进程概念的理解,明确进程和程序的区别。
2)学习进程创建的过程,进一步认识进程并发执行的实质。
3)分析进程争用资源的现象,学习解决进程互斥的方法。
4)学习解决进程同步的方法。
5)掌握Linux系统中进程间通过管道通信的具体实现。
二、实验内容及要求
1)使用系统调用函数pipe()建立一条管道,系统调用fork()分别创建两个子进程,它们分别向管道写一句话,如:
Child process1 is sending a message!
Child process2 is sending a message!
2)父进程分别从管道读出来自两个子进程的信息,显示在屏幕上。
3)这是一个设计型实验,要求自行、独立编制程序。
4)两个子进程要并发执行。
5)实现管道的互斥使用。当一个子进程正在对管道进行写操作时,另一个欲写入管道的子进程必须等待。使用系统调用lockf(fd[1],1,0)实现对管道的加锁操作,用lockf(fd[1],0,0)解除对管道的锁定。
6)实现父子进程的同步,当父进程试图从一空管道中读取数据时,便进入等待状态,直到子进程将数据写入管道返回后,才将其唤醒。
三、程序流程图
父进程
子进程P1和P2:
四、源代码及注释
#include
#include
#include
#include
#include
#include
#include
#include
int main()
{
int i,r,pid1,pid2,fd[2];
char str1[100],str2[100];
pipe(fd);//创建管道
while((pid1=fork())==-1);//创建子进程P1失败循环
if(pid1==0)子进程P1
{
lockf(fd[1],1,0);//锁住管道写端
sprintf(str1,"child process pid1 is sending messages!\n");
printf("child process pid1!\n");
write(fd[1],str1,100);//写入管道
printf("pid1=%d\n",pid1);
sleep(5);//睡眠等待
lockf(fd[1],0,0);//解锁
exit(0);//结束子进程P1
}
else
{
while((pid2=fork())==-1);//创建子进程P2失败循环
if(pid2==0)//子进程P2
{
lockf(fd[1],1,0);锁住管道写端
sprintf(str1,"child process pid2 is sending messages!\n");
printf("child process pid2!\n");
write(fd[1],str1,100);//写入管道
printf("pid2=%d\n",pid2);
sleep(5);//睡眠等待
lockf(fd[1],0,0);//解锁
exit(0);//结束子进程P2
}
wait(0);//子进程P1返回子进程
if(r=read(fd[0],str2,100)==-1)//读取失败
printf("can't read pipe\n");
else printf("%s\n",str2);
wait(0);//子进程P2返回
if(r=read(fd[0],str2,100)==-1)
printf("can't read pipe\n");
else printf("%s\n",str2);
exit(0);
}
return 0;
}
五、运行结果及说明
六、课后习题
1)指出父进程与两个子进程并发执行的顺序,并说明原因。
父进程创建子进程1,然后子进程1执行,子进程1执行完毕之后父进程执行并创建子进程2,子进程2执行,其执行完毕之后父进程执行,程序结束。
即子进程先执行,然后父进程才执行。
这是由进程的同步机制决定的,因为只有子进程向管道中写入信息后,父进程才能读取;否则父进程自己调用wait()系统调用将自己阻塞,将处理机交由子进程。
2)若不对管道加以互斥控制,会有什么后果?
管道进行互斥控制,是为防止两个子进程对管道资源进行争夺而产生信息丢失或覆盖。如果不加控制,那么可能一个子进程写入的信息还没来得及被父进程读出,另一个子进程又先写入信息,那么之前的进程写入的信息将被覆盖,父进程也就读不到之前进程传递来的信息了。
3)说明你是如何实现父子进程之间的同步的。
1、父进程读出之前确定管道中有数据,否则阻塞自己。
这一点很容一般到,通过系统调用wait()函数,即可以实现,当子进程结束时父进程才执行,那么此时管道中肯定已经有子进程写入的数据了。
2、子进程在写入之前要确定管道中的数据已经被父进程读
出,否则不能写入或者阻塞自己。
3、这可以通过进程间的互斥来间接的办到。因为子进程间的
互斥,所以每个子进程在执行开始都对管道pipe加锁,那么这样同时就只能有一个子进程向管道写入数据,并且子进程在向管道中写入数据后还要调用sleep()系统调用睡眠若干时间,那么这样就可以保证父进程能够从管道中读出数据。然后下一子进程才能写入。那么这样就保证了开头所说的子进程在写入之前要确定管道中的数据已经被父进程读出,否则不能写入或者阻塞自己。