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

下载本文档

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

文档简介

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

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

3、课堂上的知识通过自己设计的程序表示出来,加深了岁理论知识的理解目的。目录444(1)4(2).4461.62.81213141919三、系统环境1、硬件环境:Intel(R)Core (TM)2 Duo CPUE7200 2.53GHz1.59GHz,2.00GB的内存2、软件环境Microsoft Windows XPProfesstonal版本 2002Service Pack 3四、设计目的利用 UNIX 系统提供的管道机制实现进程间的通信。(1)管道通信。利用pipe() 和 lockf() 系统调用,编写程序,实现同族进程间的通信。使用系统调用pipe() 建立一条管道线;创建子进程

4、P1,P2,。子进程 Pi 分别向管道各写信息,而父进程则从管道中读出来自于各子进程的信息,实现进程家族间无名管道通讯。扩展之,使之成为客户/服务器模式,并完成一定的任务(自己定义)。(2)命名管道通信: 利用 mkfifo(name ,mode)或 mknod(name,mode,0)创建一个命名管道,然后利用它和文件部分系统调用实现不同进程间的通信。改造之,使之成为客户/服务器模式,并完成一定的任务(自己定义)。五、总体设计1.fork()创建一个新进程。用法:int fork()其中返回int取值意义如下:0:创建子进程, 从子进程返回的id 值0:从父进程返回的子进程id 值-1 :创

5、建失败2.lockf(files,function,size)用作锁定文件的某些段或者整个文件。头文件 :#include参数定义 :int lockf(files,function,size);int files,function;long size;其中 :files是文件描述符;function是锁定和解锁;1 表示锁定; 0 表示解锁; Size 是锁定或解锁的字节数,若用0, 表示从文件的当前位置到文件尾。3.read功能:从描述符为filedes的文件读信息。用法:#include ssize_t read(intfiledes, void *buff , size_tnbytes

6、 ) ;返回:读到的字节数,若已到文件尾为0,若出错为 -1 。在 UNIX/Linux可重定义为:intread(int fd,char*buff ,unsigned nbytes) ;4.write功能:向已打开的文件写数据。用法:#include ssize_t write(intfiledes, const void *buff , size_tnbytes ) ;返回值:若成功为已写入的字节数;出错为-1 。int write(int fd, char *buff , unsignednbytes ) ;文件位置指针文件位置指针: 每个打开文件都有一个与其相关联的“当前位移量”。是从

7、文件开始处计算的字节数。 通常,读、 写操作都从当前文件位置处开始,并使位移量增加所读或写的字节数。按系统默认,当打开一个文件时,除非指定O_APPEND选择项,否则该位移量被设置为0,即指向文件的开始处。文件位置指针可以通过系统调用lseek来移动。5.创建用 mkfifo 或 mknod 创建一个命名管道。以mkfifo 为例:#include #include int mkfifo(const char *fifo_name, mode_t mode);/成功返回0,否则为 -16 signal(sig,function)允许调用进程控制软中断信号的处理。头文件 :#include参数定

8、义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 的消息队列等待 msgqid1 发来消息接收消息存储到文件显示消息向 msgqid2 发送收到命令收到 exi

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

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

11、中的数据,写完后该数据即可以从读端 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(child processP2!n); /

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

13、信息数据/wait(0); / 等待第二个子进程退出/if(r=read(fd0,s,50)=-1) / 从管道读端 fd0 读取出 P1 或者 P2 写入的数据(视哪个子进程后执行到 lockf 函数) /printf(:cant read pipen); / 读取失败,打印错误信息/elseprintf(:%sn,s); / 打印读取到的信息数据/exit(0); / 主进程退出 /2、命名管道设计。命名管道的通信例子中包括client端和server 端。它们源代码文件名称分别为fifo_clt.c和 fifo_svr.c ,还有一个公共常量的有关文件被打包在文件fifo_hd.h运行时

14、,client只运行一次就将退出,而server端作为服务器仍将继续运行,你再次启动client来请求服务。FIFO的用法1、创建用mkfifo或mknod创建一个命名管道。以mkfifo为例:#include#include int mkfifo(const char *fifo_name, mode_t mode);/成功返回0,否则为 -12、使用管道一经创建,就可向普通文件一样使用。可通过系统调用open,close,read,write,unlink等进行操作。管道打开过程中,变量O_NONBLOCK将影响打开后对文件的操作。默认情况下该变量不设置,也就是以阻塞方式打开。这样可以保证

15、原子性操作。(因此可以不考虑该参数。)在操作过程中,如果对一个管道进行写操作write ,若对方没有以读方式打开将产生SIGPIPE。你可以捕获此信号进行处理。默认情况下是出现写错误。当最后一个写入者关闭了管道,将产生一个文件结束标志EOF。3、 client 、 server可以以client/server方式使用FIFO 。如果一个服务器有多个客户时,每个客户可通过一个well_known FIFO服务器连接。连接后可以通过well_known FIFO向服务器发送请求,所发信息的长度必须PIPE_BUF (4096) 。如果客户服务器模式是并发型的话,则客户机不能再通过well_know

16、n FIFO回读信息。此时可采用在已连接的客户与服务器之间建立一个私有通讯管道的办法来进行通信。该私有管道被服务器创建后可以以I/O 方式打开, 用于客户机和服务器之间进行通讯,以完成指定性工作。头文件#define my_fifo my_fifo /*定义头文件名 */#define file_name server. /*定义头文件名 */客户端程序#include#include#include#includefifo_hd.hmain(int argc,char *argv)int fd1,fd2,pid,pid1; /*定义管道 */charmy_buf100;charmy_fil1

17、00;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,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)

18、;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 %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)fpri

19、ntf(stderr,Different occurs!n);strcpy(my_buf,0000000000);write(fd2,my_buf,5);sleep(5);close(fd2);close(fd1);服务器程序#include#include#include#include#includefifo_hd.hvoidterminate();int well_known_id,tmp_id;chartmp_fil100;main(int argc,char *argv)int fd1,fd2;pid_tpid;charmy_buf100,my_fil100,my_tmp100;sp

20、rintf(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(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 N

21、ew 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_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(m

22、y_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_IRWXG|S_IRWXO)=-1)fprintf(stderr,Create my_fil:%s FIFO Error!n,my_fil);exit(-1);/*错误 */system(ls server*);if(fd2=open(my_

23、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_tmp,5)!=5)fprintf(stderr,read %s Erro

24、r!n,my_fil);close(fd2); close(fd1);unlink(my_fil);unlink(my_fifo);exit(-5);/*退出 */else if(strncmp(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

25、 %s!n,my_fil);unlink(my_fil);/unlink(my_fifo);exit(0);/*成功实现管道通信*/void terminate()if(well_known_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 liulong.c执行:./a.out结果:任务

26、二编译方法是:编译:cc o fifo_svr fifo_srv.ccc o fifo_clt fifo_client.c执行:先启动 server 端程序,方法为:./fifo_svr服务端:再换一个终端运行client 端,方法是:./fifo_clt客户端:运行时, client 只运行一次就将退出,而server 端作为服务器仍将继续运行,你再次启动 client 来请求服务。正常:管道实现通信出现错误如下:服务器运行起初正常, 然后当与客户端建立通信时由于客户端程序出错, 导致整个通信出现错误。由客户端引起的服务器程序运行出现错误当服务器输送文件时,打开服务器出现错误继续结果一样:客

27、户端程序运行出现错误服务器等待通信连接:服务器程序正常运行八、设计中遇到的问题及解决方法在编写无名管道前了解到 pipe()创建的管道只能实现父子进程或者兄弟进程之间的通信, 但是还是遇到了以下几个问题: 1、 怎样实现不同子进程互斥的访问管道? 2、是各个子进程都写完之后父进程一起读,还是在每个子进程一写完父进程就马上读, 那么怎样去通知父进程去读呢?经过查阅相关资料得知, 为解决第一个问题而引入了 lockf ()函数用于实现上锁与解锁,此函数放在读写之前执行。为解决第二问题而引入 sleep()和 wait()函数用以实现睡眠与等待。在编写有名管道前经查阅相关资料得知用 mknod()或

28、者 mkfifo ()函数调用创建有名管道从而实现在任意两个文件间的通信, 该管道可以像普通文件一样read、write 、open。由于这是个新接触的知识,以往没有练习过,所以出现的问题较多:首先,怎样才能实现客户 / 服务器模式,使其可在两个终端上交互运行?其次,怎样控制读写以及输入输出?经过查阅相关资料模仿、 拷贝、小组讨论即可得出基本模块。最后使用 signal(SIGINT,terminate)函数发送中断信号退出程序。经调试后最后可在机器上运行。九、源程序清单#include #include #include int pid1,pid2;main( )int fd2;char o

29、utpipe100,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);exit(0);elsewhile(pid2=fork( )=-1);if(pid2=0)lockf(fd1,1,0);sprintf(outpipe,child 2 process is sending message!);write(fd1,

30、outpipe,50);sleep(5);lockf(fd1,0,0);exit(0);elsewait(0);read(fd0,inpipe,50);printf(%sn,inpipe);wait(0);read(fd0,inpipe,50);printf(%sn,inpipe);exit(0);头文件 :#define my_fifo my_fifo#define file_name server.客户端程序 :#include#include#include#includefifo_hd.hmain(int argc,char *argv)int fd1,fd2,pid,pid1;cha

31、rmy_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,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

32、_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 %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)!

33、=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#includefifo_hd.hvoidterminate();int well_known_id,tmp_id;chartmp_fil100;main(int argc,char *argv)int fd1,fd2;pid_tpid;charmy_buf100,my_fil100,my

34、_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(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

35、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_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

36、);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_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);

温馨提示

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

评论

0/150

提交评论