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

下载本文档

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

文档简介

第第页操作系统管道通信河南城建学院

《操作系统》课程设计说明书

设计题目:管道通信

专业:计算机科学与技术

指导老师:邵国金郭猛薛冰

班级:0814102

学号:081410217

姓名:金贺

同组人:李乾坤邵光光

计算机科学与工程系

2022年1月10日

授课:***

前言

课程设计是检测同学课程效果的重要手段,是训练同学通过所学的知识解决实际问题的重要方式,同时也是实践性教学中的一个重要环节,它以某以课程为基础,可以涉及和课程相关的各个方面,是一门独立于课程之外的非常课程。课程设计是让同学对所学的课程更全面的学习和应用,理解和掌控课程的相关知识。《操作系统》是一门重要的专业课,是计算机理论和应用的核心基础课程。

操作系统课程设计,是一次对多学知识的综合演练,要求同学在操作系统的设计理念、整体机构、模块划分、数据结构的选择和应用、算法的设计及其实现等方面,加深对课程基本内容的理解,同时,在课程设计方法以及上机操作等基本技能和科学作风方面收到比较系统和严格的训练。

在这次的课程设计中我们选择的题目是进程间通信消息机制的设计,实现消息的创建、发送和接收及在server端创建一个服务函数,从而形成C/S通讯模式。消息机制是消息通过消息队列的方式进行进程间消息的传递,通过此次课程设计,全面理解消息机制进程间通信方法。实现把死板的课本知识变得生动有趣,激发了同学的积极性。把学过的计算机操作系统的知识强化,能够把课堂上的知识通过自己设计的程序表示出来,加深了岁理论知识的理解目的。

授课:***

目次

一、(4)

二、(4)

三、设计题目及要求(4)

(1)设计管道通信(4)

(2)设计命名管道(4)

四、总体设计(4)

五、具体设计(6)

1、实现管道通信(6)

2、命名管道设计(8)

六、调试与测试方法(12)

七、执行结果及分析(13)

八、源程序清单(14)

九、心得体会(19)

十、

#includestdio.h

main()

{

inti,r,p1,p2,fd[2];

charbuf[50],s[50];

pipe(fd);//创建匿名管道,fd[0]为读端,fd[1]为写端//

while((p1=fork())==-1);//创建子进程P1,直至胜利为止〔p1!=-1〕//

if(p1==0)//子进程P1执行规律//

{

lockf(fd[1],1,0);//锁定管道写端,保证写入数据的完整性//

sprintf(buf,childprocessP1issendingmessages!\n);//在buf中填入预备写入管道的信息数据printf(childprocessP1!\n);//打印“子进程P1正在运行”//

write(fd[1],buf,50);//向管道写端fd[1]写入buf中的数据,写完后该数据即可以从读端fd[0]读出//

sleep(5);//睡眠5秒//

lockf(fd[1],0,0);//解锁管道写端//

e*it(0);//子进程P1退出//

}

else//主进程的执行规律//

{

while((p2=fork())==-1);//创建第二个子进程P2//

if(p2==0)//子进程P2的执行规律//

{

lockf(fd[1],1,0);//锁定管道写端,保证数据写入完整//

sprintf(buf,childprocessP2issendingmessages!\n);//在buf中填入预备写入管道的信息数据

授课:***

printf(childprocessP2!\n);//打印“子进程P2正在运行”//

write(fd[1],buf,50);//向管道写端fd[1]写入buf中的数据,写完后该数据即可从读端fd[0]读出//

sleep(5);//睡眠5秒//

lockf(fd[1],0,0);//解锁管道写端//

e*it(0);//子进程P2退出//

}

//以下为主进程执行规律//

wait(0);//等待某个子进程退出//

if(r=read(fd[0],s,50)==-1)//从管道读端fd[0]读取P1或者P2写入的数据〔视哪个子进程抢先执行到lockf函数〕//

{

printf(:cantreadpipe\n);//读取失败,打印错误信息//

}

else

{

printf(:%s\n,s);//打印出读到的信息数据//

}

wait(0);//等待第二个子进程退出//

if(r=read(fd[0],s,50)==-1)//从管道读端fd[0]读取出P1或者P2写入的数据〔视哪个子进程后执行到lockf函数〕//

{

printf(:cantreadpipe\n);//读取失败,打印错误信息//

}

else

{

printf(:%s\n,s);//打印读取到的信息数据//

}

e*it(0);//主进程退出//

}

}

2、命名管道设计。

命名管道的通信例子中包括client端和server端。它们源代码文件名称分别为fifo_clt.c和fifo_svr.c,还有一个公共常量的有关文件被打包在文件fifo_hd.h

运行时,client只运行一次就将退出,而server端作为服务器仍将继续运行,你再次启动client来恳求服务。

FIFO的用法

1、创建

用mkfifo或mknod创建一个命名管道。以mkfifo为例:

#includesys/types.h

#includesys/stat.h

intmkfifo(constchar*fifo_name,mode_tmode);//胜利返回0,否那么为-1

授课:***

2、运用

管道一经创建,就可向一般文件一样运用。可通过系统调用open,close,read,write,unlink等进行操作。

管道打开过程中,变量O_NONBLOCK将影响打开后对文件的操作。默认状况下该变量不设置,也就是以堵塞方式打开。这样可以保证原子性操作。〔因此可以不考虑该参数。〕在操作过程中,假如对一个管道进行写操作write,假设对方没有以读方式打开将产生SIGPIPE。你可以捕获此信号进行处理。默认状况下是涌现写错误。当最末一个写入者关闭了管道,将产生一个文件结束标识EOF。

3、client、server

可以以client/server方式运用FIFO。假如一个服务器有多个客户时,每个客户可通过一个well_knownFIFO服务器连接。连接后可以通过well_knownFIFO向服务器发送恳求,所发信息的长度需要≤PIPE_BUF(4096)。

假如客户服务器模式是并发型的话,那么客户机不能再通过well_knownFIFO回读信息。此时可采纳在已连接的客户与服务器之间建立一个私有通讯管道的方法来进行通信。该私有管道被服务器创建后可以以I/O方式打开,用于客户机和服务器之间进行通讯,以完成指定性工作。

头文件

#definemy_fifomy_fifo/*定义头文件名*/

#definefile_nameserver./*定义头文件名*/

客户端程序

#includestdio.h

#includesys/types.h

#includesys/stat.h

#includefifo_hd.h

main(intargc,char**argv)

{

intfd1,fd2,pid,pid1;/*定义管道*/

charmy_buf[100];

charmy_fil[100];

charmy1buf[100];

if((fd1=open(my_fifo,1))==-1)

{

授课:***

fprintf(stderr,Openwell_knownFIFOforreadindError!\n);

e*it(-1);/*失败*/

}

fprintf(stderr,Open%sOK!\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:%s\n,my_fil);

sleep(2);

if((fd2=open(my_fil,2))==-1){

fprintf(stderr,open%sError!\n,my_fil);

close(fd1);

e*it(-2);

}

fprintf(stderr,open%sOK!\n,my_fil);

if(read(fd2,my1buf,5)!=0){

my1buf[5]=\0;

fprintf(stderr,Readfrommy_buf:%s!\n\tmy1buf:%s,my_buf,my1buf);

if(strncmp(my_buf,my1buf,5)!=0){

fprintf(stderr,Differentoccurs!\n);

}

strcpy(my_buf,0000000000);

write(fd2,my_buf,5);

//sleep(5);

close(fd2);

close(fd1);

}

}

}

服务器程序

#includestdio.h

#includesignal.h

#includesys/types.h

#includesys/stat.h

#includefifo_hd.h

voidterminate();

intwell_known_id,tmp_id;

chartmp_fil[100];

main(intargc,char**argv)

{

授课:***

intfd1,fd2;

pid_tpid;

charmy_buf[100],my_fil[100],my_tmp[100];

sprintf(my_buf,rm-f%s/dev/null,my_fifo);

system(my_buf);//doshellcmdrm-fmy_fifo/dev/null

well_known_id=tmp_id=-1;

signal(SIGINT,terminate);

if(mkfifo(my_fifo,S_IRW*U|S_IRW*G|S_IRW*O)==-1){

fprintf(stderr,CreateWell_knownFIOFError!\n);

e*it(-1);/*创建失败*/

}

fprintf(stderr,mkfifoOK!\n);

fprintf(stderr,ANewSeession!Imwaitingconnection...\n);loop1:/*输出字符串*/

if((fd1=open(my_fifo,0))==-1){

fprintf(stderr,Openwell_knownFIFOforreadindError!\n);

unlink(my_fifo);/*断链接*/

e*it(-2);

}

well_known_id=fd1;

tmp_id=-1;

fprintf(stderr,openmy_fifoOK!\n);

if(read(fd1,my_buf,20)!=0){

fprintf(stderr,My_buff=%s\n,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();

gotoloop1;

}

fprintf(stderr,Tmp_FIFOis:%s|\n,my_fil);

if(mkfifo(my_fil,S_IRW*U|S_IRW*G|S_IRW*O)==-1){

fprintf(stderr,Createmy_fil:%sFIFOError!\n,my_fil);

e*it(-1);/*错误*/

}

//system(lsserver*);

if((fd2=open(my_fil,2))==-1){

fprintf(stderr,Open%sError!:%d\n,my_fil,fd2);

close(fd1);unlink(my_fifo);

e*it(-3);

授课:***

}

tmp_id=fd2;

if(write(fd2,my_buf,5)!=5){

fprintf(stderr,Write%sError!\n,my_fil);

close(fd2);close(fd1);

unlink(my_fil);unlink(my_fifo);

e*it(-4);/*退出*/

}

sleep(1);

if(read(fd2,my_tmp,5)!=5){

fprintf(stderr,read%sError!\n,my_fil);

close(fd2);close(fd1);

unlink(my_fil);unlink(my_fifo);

e*it(-5);/*退出*/

}

else{

if(strncmp(my_tmp,00000,5)!=0){

close(fd2);close(fd1);

fprintf(stderr,Filedtofinishtalkingwith%s!\n,my_fil);

unlink(my_fil);

e*it(-1);/*失败*/

//gotoloop1;

}

else{

close(fd2);close(fd1);

fprintf(stderr,OKtotalkingwith%s!\n,my_fil);

unlink(my_fil);

//unlink(my_fifo);

e*it(0);/*胜利实现管道通信*/

}

}

}

voidterminate()

{

if(well_known_id!=-1){

close(well_known_id);unlink(my_fifo);

}

if(tmp_id!=-1){

close(tmp_id);unlink(tmp_fil);

}

fprintf(stderr,TheServerProgramstopedbySignal:SIGINT!\n);

e*it(0);

}

七、调试与测试

授课:***

任务一编译方法:

编译:

ccliulong.c

执行:

./a.out

结果:

任务二编译方法是:

编译:

cc–ofifo_svrfifo_srv.c

cc–ofifo_cltfifo_client.c

执行:

先启动server端程序,方法为:

./fifo_svr

服务端:

再换一个终端运行client端,方法是:

授课:***

./fifo_clt

客户端:

运行时,client只运行一次就将退出,而server端作为服务器仍将继续运行,你再次启动client来恳求服务。

任务一运行结果正常:管道实现通信

任务二运行结果涌现错误如下:

服务器运行起初正常,然后当与客户端建立通信时由于客户端程序出错,导致整个通信涌现错误。

授课:***

授课:

***

由客户端引起的服务器程序运行涌现错误

当服务器输送文件时,打开服务器涌现错误继续结果一样:

客户端程序运行涌现错误

服务器等待通信连接:

服务器程序正常运行

八、设计中遇到的问题及解决方法

在编写无名管道前了解到pipe〔〕创建的管道只能实现父子进程或者兄弟进程之间的通信,但是还是遇到了以下几个问题:1、怎样实现不同子进程互斥的访问管道?2、是各个子进程都写完之后父进程一起读,还是在每个子进程一写完父进程就立刻读,那么怎样去通知父进程去读呢?经过查阅相关资料得知,为解决第一个问题而引入了lockf〔〕函数用于实现上锁与解锁,此函数放在读写之前执行。为解决第二问题而引入sleep〔〕和wait〔〕函数用以实现睡眠与等待。

在编写出名管道前经查阅相关资料得知用mknod〔〕或者mkfifo〔〕函数调用创建出名管道从而实现在任意两个文件间的通信,该管道可以像一般文件一样read、write、open。由于这是个新接触的知识,以往没有练习过,所以涌现的问题较多:首先,怎样才能实现客户/服务器模式,使其可在两个终端上交互运行?其次,怎样掌握读写以及输入输出?经过查阅相关资料仿照、拷贝、小组争论即可得出基本模块。最末运用signal(SIGINT,terminate)函数发送中断信号退出程序。经调试后最末可在机器上运行。

九、源程序清单

任务1

#includeunistd.h

#includesignal.h

#includestdio.h

intpid1,pid2;

main()

{

intfd[2];

charoutpipe[100],inpipe[100];

pipe(fd);

while((pid1=fork())==-1);

if(pid1==0)

{

授课:***

温馨提示

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

评论

0/150

提交评论