操作系统管道通信_第1页
操作系统管道通信_第2页
操作系统管道通信_第3页
操作系统管道通信_第4页
操作系统管道通信_第5页
已阅读5页,还剩23页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、-作者xxxx-日期xxxx操作系统管道通信【精品文档】河南城建学院操作系统课程设计说明书设计题目: 管道通信 专 业: 计算机科学与技术 指导教师: 邵国金 郭猛 薛冰 班 级: 0814102 学 号: 081410217 姓 名: 金 贺 同 组 人: 李乾坤 邵光光 计算机科学与工程系2011年1 月 10 日前言课程设计是检测学生课程效果的重要手段,是训练学生通过所学的知识解决实际问题的重要方式,同时也是实践性教学中的一个重要环节,它以某以课程为基础,可以涉及和课程相关的各个方面,是一门独立于课程之外的特殊课程。课程设计是让学生对所学的课程更全面的学习和应用,理解和掌握课程的相关知识

2、。操作系统是一门重要的专业课,是计算机理论和应用的核心基础课程。操作系统课程设计,是一次对多学知识的综合演练,要求学生在操作系统的设计理念、整体机构、模块划分、数据结构的选择和应用、算法的设计及其实现等方面,加深对课程基本内容的理解,同时,在课程设计方法以及上机操作等基本技能和科学作风方面收到比较系统和严格的训练。在这次的课程设计中我们选择的题目是进程间通信消息机制的设计,实现消息的创建、发送和接收及在server端创建一个服务函数,从而形成C/S通讯模式。消息机制是消息通过消息队列的方式进行进程间消息的传递,通过此次课程设计,全面理解消息机制进程间通信方法。实现把死板的课本知识变得生动有趣,

3、激发了学生的积极性。把学过的计算机操作系统的知识强化,能够把课堂上的知识通过自己设计的程序表示出来,加深了岁理论知识的理解目的。目 录一、.4二、.4三、设计题目及要求.4(1)设计管道通信4(2)设计命名管道.4四、总体设计.4五、详细设计.61、实现管道通信 .6 2、命名管道设计 .8六、调试与测试方法.12七、执行结果及分析.13八、源程序清单.14九、心得体会.19十、参考文献.19三、系统环境1、硬件环境:Intel(R)Core (TM)2 Duo CPU2、软件环境 Microsoft Windows XPProfesstonal版本 2002Service Pack 3 四、

4、设计目的利用UNIX系统提供的管道机制实现进程间的通信。(1)管道通信。利用pipe()和lockf()系统调用,编写程序,实现同族进程间的通信。使用系统调用pipe()建立一条管道线;创建子进程P1,P2,。子进程Pi分别向管道各写信息,而父进程则从管道中读出来自于各子进程的信息,实现进程家族间无名管道通讯。扩展之,使之成为客户/服务器模式,并完成一定的任务(自己定义)。(2)命名管道通信:利用mkfifo(name,mode)或mknod(name,mode,0)创建一个命名管道,然后利用它和文件部分系统调用实现不同进程间的通信。改造之,使之成为客户/服务器模式,并完成一定的任务(自己定义

5、)。五、总体设计()创建一个新进程。用法:int fork()其中返回int取值意义如下:0:创建子进程,从子进程返回的id值0:从父进程返回的子进程id值-1:创建失败2.lockf(files,function,size)用作锁定文件的某些段或者整个文件。头文件:#include参数定义:int lockf(files,function,size);int files,function;long size;其中:files是文件描述符;function是锁定和解锁;1表示锁定;0表示解锁;Size是锁定或解锁的字节数,若用0,表示从文件的当前位置到文件尾。3.read功能:从描述符为fil

6、edes的文件读信息。用法:#include ssize_tread(int filedes, void *buff, size_t nbytes) ;返回:读到的字节数,若已到文件尾为0,若出错为-1。 在UNIX/Linux 可重定义为: intread(int fd, char *buff, unsigned nbytes) ;4.write功能:向已打开的文件写数据。用法:#include ssize_t write(int filedes, const void * buff, size_t nbytes) ;返回值:若成功为已写入的字节数;出错为-1。intwrite(int fd

7、, char *buff, unsigned nbytes) ;文件位置指针文件位置指针:每个打开文件都有一个与其相关联的“当前位移量”。是从文件开始处计算的字节数。通常,读、写操作都从当前文件位置处开始,并使位移量增加所读或写的字节数。按系统默认,当打开一个文件时,除非指定O_APPEND选择项,否则该位移量被设置为0,即指向文件的开始处。文件位置指针可以通过系统调用lseek来移动。用mkfifo或mknod创建一个命名管道。以mkfifo为例:#include#includeint mkfifo(const char *fifo_name, mode_t mode);/成功返回0,否则为

8、-16 signal(sig,function)允许调用进程控制软中断信号的处理。头文件:#include参数定义signal(sig,function)intsig;void(*function)();返回值:成功时返回旧的(以前)函数描述,失败时返回SIG_ERR。7、client、server可以以client/server方式使用FIFO。如果一个服务器有多个客户时,每个客户可通过一个well_known FIFO服务器连接。连接后可以通过well_known FIFO向服务器发送请求,所发信息的长度必须PIPE_BUF (4096)。 流程图初始化创建一个key为105、107 的消

9、息队列等待msgqid1发来消息存储到文件 接收消息 显示消息 向msgqid2发送收到命令 收到exit命令 挂起5秒 删除消息队列 退出消息的创建、发送和接收示意图初始化创建子进程server()创建成功? 由关键字获得消息队列从队列接收消息消息类型i为1时,释放队列删除队列表项 退出 六 详细设计 1、实现管道通信编制一段程序,实现进程的管道通信。使用系统调用pipe()建立一条管道线。两个子进程p1和p2分别向管道各写一句话:child 1 is sending message!child 2 is sending message!而父进程则从管道中读出来自于两个子进程的信息,显示在屏

10、幕上。#include main() int i,r,p1,p2,fd2; char buf50,s50; pipe(fd); /创建匿名管道,fd0为读端,fd1为写端/while(p1=fork()=-1); /创建子进程P1,直至成功为止(p1!=-1)/if(p1=0) /子进程P1执行逻辑/ lockf(fd1,1,0); /锁定管道写端,保证写入数据的完整性/sprintf(buf,child process P1 is sending messages!n); /在buf中填入准备写入管道的信息数据printf(child processP1!n); /打印“子进程P1正在运行”

11、 /write(fd1,buf,50); /向管道写端fd1写入buf中的数据,写完后该数据即可以从读端fd0读出/sleep(5); /睡眠5秒/lockf(fd1,0,0); /解锁管道写端/exit(0); /子进程P1退出/ else /主进程的执行逻辑/ while(p2=fork()=-1); /创建第二个子进程P2/if(p2=0) /子进程P2的执行逻辑/ lockf(fd1,1,0); /锁定管道写端,保证数据写入完整/sprintf(buf,child process P2 is sending messages!n); /在buf中填入准备写入管道的信息数据printf(

12、child processP2!n); /打印“子进程P2正在运行” /write(fd1,buf,50); /向管道写端fd1写入buf中的数据,写完后该数据即可从读端fd0读出/sleep(5); /睡眠5秒/lockf(fd1,0,0); /解锁管道写端/exit(0); /子进程P2退出/ /以下为主进程执行逻辑/wait(0); /等待某个子进程退出/if(r=read(fd0,s,50)=-1) /从管道读端fd0读取P1或者P2写入的数据(视哪个子进程抢先执行到lockf函数)/ printf(:cant read pipen); /读取失败,打印错误信息/ else print

13、f(:%sn,s); /打印出读到的信息数据/ wait(0); /等待第二个子进程退出/if(r=read(fd0,s,50)=-1) /从管道读端fd0读取出P1或者P2写入的数据(视哪个子进程后执行到lockf函数)/ printf(:cant read pipen); /读取失败,打印错误信息/ else printf(:%sn,s); /打印读取到的信息数据/ exit(0); /主进程退出/ 2、命名管道设计。运行时,client只运行一次就将退出,而server端作为服务器仍将继续运行,你再次启动client来请求服务。FIFO的用法1、创建用mkfifo或mknod创建一个命名

14、管道。以mkfifo为例:#include#includeint mkfifo(const char *fifo_name, mode_t mode);/成功返回0,否则为-12、使用管道一经创建,就可向普通文件一样使用。可通过系统调用open,close,read,write,unlink等进行操作。管道打开过程中,变量O_NONBLOCK将影响打开后对文件的操作。默认情况下该变量不设置,也就是以阻塞方式打开。这样可以保证原子性操作。(因此可以不考虑该参数。)在操作过程中,如果对一个管道进行写操作write,若对方没有以读方式打开将产生SIGPIPE。你可以捕获此信号进行处理。默认情况下是出

15、现写错误。当最后一个写入者关闭了管道,将产生一个文件结束标志EOF。3、client、server可以以client/server方式使用FIFO。如果一个服务器有多个客户时,每个客户可通过一个well_known FIFO服务器连接。连接后可以通过well_known FIFO向服务器发送请求,所发信息的长度必须PIPE_BUF (4096)。如果客户服务器模式是并发型的话,则客户机不能再通过well_known FIFO回读信息。此时可采用在已连接的客户与服务器之间建立一个私有通讯管道的办法来进行通信。该私有管道被服务器创建后可以以I/O方式打开,用于客户机和服务器之间进行通讯,以完成指定

16、性工作。头文件#define my_fifo my_fifo /*定义头文件名*/#define file_name server. /*定义头文件名*/客户端程序#include#include#include#includefifo_hd.hmain(int argc,char *argv)intfd1,fd2,pid,pid1; /* 定义管道*/charmy_buf100;charmy_fil100;charmy1buf100;if(fd1=open(my_fifo,1)=-1)fprintf(stderr,Open well_known FIFO for readind Error!

17、n);exit(-1); /*失败*/ fprintf(stderr,Open %s OK!n,my_fifo);pid=getpid();sprintf(my_buf,%5.5d%6.6d%7.7d,pid,pid*10,pid*20);if(write(fd1,my_buf,20)!=0)strcpy(my_fil,file_name); /*拷贝*/strncat(my_fil,my_buf,5);fprintf(stderr,Send_fil: %sn,my_fil);sleep(2);if(fd2=open(my_fil,2)=-1)fprintf(stderr,open %s Er

18、ror!n,my_fil);close(fd1);exit(-2);fprintf(stderr,open %s OK!n,my_fil);if(read(fd2,my1buf,5)!=0)my1buf5=0;fprintf(stderr,Read from my_buf:%s!ntmy1buf:%s,my_buf,my1buf);if(strncmp(my_buf,my1buf,5)!=0)fprintf(stderr,Different occurs!n);strcpy(my_buf,0000000000);write(fd2,my_buf,5);/sleep(5);close(fd2);

19、close(fd1);服务器程序#include#include#include#include#includefifo_hd.hvoidterminate();intwell_known_id,tmp_id;chartmp_fil100;main(int argc,char *argv)intfd1,fd2;pid_tpid;charmy_buf100,my_fil100,my_tmp100;sprintf(my_buf,rm -f %s /dev/null,my_fifo);system(my_buf);/do shell cmd rm -f my_fifo /dev/nullwell_k

20、nown_id=tmp_id=-1;signal(SIGINT,terminate);if(mkfifo(my_fifo,S_IRWXU|S_IRWXG|S_IRWXO)=-1)fprintf(stderr,Create Well_known FIOF Error!n);exit(-1); /*创建失败*/fprintf(stderr,mkfifo OK!n);fprintf(stderr,A New Seession! Im waiting connection.n);loop1: /*输出字符串*/if(fd1=open(my_fifo,0)=-1)fprintf(stderr,Open

21、well_known FIFO for readind Error!n);unlink(my_fifo); /*断链接*/exit(-2); well_known_id=fd1;tmp_id=-1;fprintf(stderr,open my_fifo OK!n);if(read(fd1,my_buf,20)!=0)fprintf(stderr,My_buff=%sn,my_buf);strcpy(my_fil,file_name);strncat(my_fil,my_buf,5);strcpy(tmp_fil,my_fil);if(pid=fork()!=0)close(fd1);wait(

22、);goto loop1;fprintf(stderr,Tmp_FIFO is: %s|n,my_fil);if(mkfifo(my_fil,S_IRWXU|S_IRWXG|S_IRWXO)=-1)fprintf(stderr,Create my_fil:%s FIFO Error!n,my_fil);exit(-1); /*错误*/ /system(ls server*);if(fd2=open(my_fil,2)=-1)fprintf(stderr,Open %s Error!:%dn,my_fil,fd2);close(fd1); unlink(my_fifo);exit(-3);tmp

23、_id=fd2;if(write(fd2,my_buf,5)!=5)fprintf(stderr,Write %s Error!n,my_fil);close(fd2); close(fd1);unlink(my_fil); unlink(my_fifo);exit(-4); /*退出*/sleep(1);if(read(fd2,my_tmp,5)!=5)fprintf(stderr,read %s Error!n,my_fil);close(fd2); close(fd1);unlink(my_fil); unlink(my_fifo);exit(-5); /*退出*/else if(str

24、ncmp(my_tmp,00000,5)!=0)close(fd2);close(fd1);fprintf(stderr,Filed to finish talking with %s!n,my_fil);unlink(my_fil);exit(-1); /*失败*/goto loop1;elseclose(fd2);close(fd1);fprintf(stderr,OK to talking with %s!n,my_fil);unlink(my_fil);/unlink(my_fifo);exit(0); /*成功实现管道通信*/void terminate()if(well_known

25、_id!=-1)close(well_known_id); unlink(my_fifo);if(tmp_id!=-1)close(tmp_id);unlink(tmp_fil);fprintf(stderr,The Server Program stoped by Signal:SIGINT!n);exit(0);七、调试与测试任务一编译方法: 编译:执行:结果:任务二编译方法是:编译:cc cc 执行:先启动server端程序,方法为:./fifo_svr服务端:再换一个终端运行client端,方法是:./fifo_clt客户端:运行时,client只运行一次就将退出,而server端作为

26、服务器仍将继续运行,你再次启动client来请求服务。正常:管道实现通信出现错误如下:服务器运行起初正常,然后当与客户端建立通信时由于客户端程序出错,导致整个通信出现错误。 由客户端引起的服务器程序运行出现错误当服务器输送文件时,打开服务器出现错误继续结果一样:客户端程序运行出现错误服务器等待通信连接: 服务器程序正常运行八、设计中遇到的问题及解决方法 在编写无名管道前了解到pipe()创建的管道只能实现父子进程或者兄弟进程之间的通信,但是还是遇到了以下几个问题:1、 怎样实现不同子进程互斥的访问管道?2、是各个子进程都写完之后父进程一起读,还是在每个子进程一写完父进程就马上读,那么怎样去通知

27、父进程去读呢?经过查阅相关资料得知,为解决第一个问题而引入了lockf()函数用于实现上锁与解锁,此函数放在读写之前执行。为解决第二问题而引入sleep()和wait()函数用以实现睡眠与等待。 在编写有名管道前经查阅相关资料得知用mknod()或者mkfifo()函数调用创建有名管道从而实现在任意两个文件间的通信,该管道可以像普通文件一样read、write、open。由于这是个新接触的知识,以往没有练习过,所以出现的问题较多:首先,怎样才能实现客户/服务器模式,使其可在两个终端上交互运行? 其次,怎样控制读写以及输入输出?经过查阅相关资料模仿、拷贝、小组讨论即可得出基本模块。最后使用sig

28、nal(SIGINT,terminate)函数发送中断信号退出程序。经调试后最后可在机器上运行。九、源程序清单#include #include #include int pid1,pid2; main( ) int fd2;char outpipe100,inpipe100;pipe(fd); while (pid1=fork( )=-1);if(pid1=0) lockf(fd1,1,0); sprintf(outpipe,child 1 process is sending message!); write(fd1,outpipe,50); sleep(5); lockf(fd1,0,0

29、); exit(0); else while(pid2=fork( )=-1); if(pid2=0) lockf(fd1,1,0); sprintf(outpipe,child 2 process is sending message!); write(fd1,outpipe,50); sleep(5); lockf(fd1,0,0); exit(0); else wait(0); read(fd0,inpipe,50); printf(%sn,inpipe); wait(0); read(fd0,inpipe,50); printf(%sn,inpipe); exit(0); 头文件:#d

30、efine my_fifo my_fifo#define file_name server.客户端程序:#include#include#include#includefifo_hd.hmain(int argc,char *argv)intfd1,fd2,pid,pid1;charmy_buf100;charmy_fil100;charmy1buf100;if(fd1=open(my_fifo,1)=-1)fprintf(stderr,Open well_known FIFO for readind Error!n);exit(-1); fprintf(stderr,Open %s OK!n

31、,my_fifo);pid=getpid();sprintf(my_buf,%5.5d%6.6d%7.7d,pid,pid*10,pid*20);if(write(fd1,my_buf,20)!=0)strcpy(my_fil,file_name);strncat(my_fil,my_buf,5);fprintf(stderr,Send_fil: %sn,my_fil);sleep(2);if(fd2=open(my_fil,2)=-1)fprintf(stderr,open %s Error!n,my_fil);close(fd1);exit(-2);fprintf(stderr,open

32、%s OK!n,my_fil);if(read(fd2,my1buf,5)!=0)my1buf5=0;fprintf(stderr,Read from my_buf:%s!ntmy1buf:%s,my_buf,my1buf);if(strncmp(my_buf,my1buf,5)!=0)fprintf(stderr,Different occurs!n);strcpy(my_buf,0000000000);write(fd2,my_buf,5);/sleep(5);close(fd2);close(fd1);服务器程序:#include#include#include#include#incl

33、udefifo_hd.hvoidterminate();intwell_known_id,tmp_id;chartmp_fil100;main(int argc,char *argv)intfd1,fd2;pid_tpid;charmy_buf100,my_fil100,my_tmp100;sprintf(my_buf,rm -f %s /dev/null,my_fifo);system(my_buf);/do shell cmd rm -f my_fifo /dev/nullwell_known_id=tmp_id=-1;signal(SIGINT,terminate);if(mkfifo(

34、my_fifo,S_IRWXU|S_IRWXG|S_IRWXO)=-1)fprintf(stderr,Create Well_known FIOF Error!n);exit(-1);fprintf(stderr,mkfifo OK!n);fprintf(stderr,A New Seession! Im waiting connection.n);loop1:if(fd1=open(my_fifo,0)=-1)fprintf(stderr,Open well_known FIFO for readind Error!n);unlink(my_fifo);exit(-2); well_know

35、n_id=fd1;tmp_id=-1;fprintf(stderr,open my_fifo OK!n);if(read(fd1,my_buf,20)!=0)fprintf(stderr,My_buff=%sn,my_buf);strcpy(my_fil,file_name);strncat(my_fil,my_buf,5);strcpy(tmp_fil,my_fil);if(pid=fork()!=0)close(fd1);wait();goto loop1;fprintf(stderr,Tmp_FIFO is: %s|n,my_fil);if(mkfifo(my_fil,S_IRWXU|S

36、_IRWXG|S_IRWXO)=-1)fprintf(stderr,Create my_fil:%s FIFO Error!n,my_fil);exit(-1); /system(ls server*);if(fd2=open(my_fil,2)=-1)fprintf(stderr,Open %s Error!:%dn,my_fil,fd2);close(fd1); unlink(my_fifo);exit(-3);tmp_id=fd2;if(write(fd2,my_buf,5)!=5)fprintf(stderr,Write %s Error!n,my_fil);close(fd2); close(fd1);unlink(my_fil); unlink(my_fifo);exit(-4);sleep(1);if(read(fd2,my_t

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论