2003级《操作系统》课程设计指导二-----进程间通信设计2006/6/20沈奕鹏管建军一、设计目的Linux系统的进程通信机构(IPC)允许在任意进程间大批量地交换数据。本实验的目的是了解和熟悉Linux支持的消息通信机制、共享存储区机制及信息量机制。二、设计内容1.消息的创建,发送和接收。①使用系统调用msgget(),msgsnd(),msgrev()及msgctl()编制一长度为1K的消息的发送和接收程序。②观察上面程序,说明控制消息队列系统调用msgctl()在此起什么作用?2.共享存储区的创建、附接和断接。使用系统调用shmget(),shmat(),sgmdt(),shmctl(),编制一个与上述功能相同的程序。三、指导步骤1.消息的创建、发送和接收(任务)使用系统调用msgget(),msgsnd(),msgrev(),及msgctl()编制一长度为1K的消息发送和接收的程序。(程序设计(1)为了便于操作和观察结果,用一个程序作为“引子”,先后fork()两个子进程,SERVER和CLIENT,进行通信。(2)SERVER端建立一个Key为75的消息队列,等待其他进程发来的消息。当遇到类型为1的消息,则作为结束信号,取消该队列,并退出SERVER。SERVER每接收到一个消息后显示一句“(server)received。(3)CLIENT端使用key为75的消息队列,先后发送类型从10到1的消息,然后退出。最后的一个消息,即是SERVER端需要的结束信号。CLIENT每发送一条消息后显示一句“(client)sent”。(4)父进程在SERVER和CLIENT均退出后结束。程序)/*e-2-1*/#includestdio.h#includesys/types.h#includesys/msg.h#includesys/ipc.h#defineMSGKEY75/*定义关键词MEGKEY*/structmsgform/*消息结构*/{longmtype;charmtext[l030];/*文本长度*/}msg;intmsgqid,i;voidCLIENT(){inti;msgqid=msgget(MSGKEY,0777);for(i=10;i=1;i--){msg.mtype=i;printf((client)sent\n);msgsnd(msgqid,&msg,1024,0);/*发送消息msg入msgid消息队列*/}exit(0);}voidSERVER(){msgqid=msgget(MSGKEY,0777|IPC_CREAT);/*由关键字获得消息队列*/do{msgrcv(msgqid,&msg,1030,0,0);/*从msgqid队列接收消息msg*/printf((server)received\n);}while(msg.mtype!=1);/*消息类型为1时,释放队列*/msgctl(msgqid,IPC_RMID,0);exit(O);}intmain(){while((i=fork())==-1);if(!i)SERVER();while((i=fork())==-1);if(!i)CLIENT();wait(0);wait(0);}(结果)从理想的结果来说,应当是每当Clinet发送一个消息后,Server接收该消息,Clinet再发送下一条。也就是说“(Clinet)sent和“(server)received的字样应该在屏幕上交替出现。实际的结果大多是,先由Clinet发送了两条消息,然后Server接收一条消息。此后C1inet-Server交替发送和接收消息。最后Server一次接收两条消息。Client和Server分别发送和接收了10条消息,与预期设想一致。(分析)message的传送和控制并不保证完全同步,当一个程序不在激活状态的时候,它完全可能继续睡眠,造成了上面的现象,在多次sendmessage后才receivemessage。这一点有助于理解消息传送的实现机理。2.共享存储区的创建,附接和断接(任务)使用系统调用shmget(),sgmat(),smgdt(),shmctl(),编制一个与上述相同功能的程序。程序设计(1)为了便于操作和观察结果,用一个程序作为“引子”,先后fork()两个子进程,SERVER和CLIENT,进行通信。(2)SERVER端建立一个Key为75的共享区,并将第一个字节置为-1。作为数据空的标志。等待其他进程发来的消息。当该字节的值发生变化时,表示收到了信息,进行处理。然后再次把它的值设为-1。如果遇到的值为0,则视为结束信号,取消该队列,并退出SERVER。SERVER每接收到一次数据后显示“(server)received”。(3)CLIENT端建立一个Key为75的共享区,当共享取得第一个字节为-1时,Server端空闲,可发送请求。CLIENT随即填入9到0。期间等待Server端的再次空闲。进行完这些操作后,CLIENT退出。CLIENT每发送一次数据后显示“(client)sent。(4)父进程在SERVER和CLIENT均退出后结束。(程序)/*e-2-2*/#includesys/types.h#includesys/msg.h#includesys/ipc.h#defineSHMKEY75/*定义共享区关键词*/intshmid,i;int*addr;voidCLIENT(){inti;shmid=shmget(SHMKEY,1024,0777);/*获取共享区,长度1024,关键词SHMKEY*/addr=shmat(shmid,0,0);/*共享区起始地址为addr*/for(i=9;i=0;i--){while(*addr!=-1);printf((client)sent\n);/*打印(client)sent*/*addr=i;/*把i赋给addr*/}exit(O);}voidSERVER(){shmid=shmget(SHMKEY,1024,0777|IPC_CREAT);/*创建共享区*/addr=shmat(shmid,0,0);/*共享区起始地址为addr*/do{*addr=-1;while(*addr==-1);printf((server)received\n);/*服务进程使用共享区*/}while(*addr);shmctl(shmid,IPC_RMID,0);exit(O);}voidmain(){while((i=fork())==-1);if(!i)SERVER();while((i=fork())==-1);if(!i)CLIENT();wait(O);wait(O)'}(结果)运行的结果和预想的完全一样。但在运行的过程中,发现每当client发送一次数据后,server要等待大约0.1秒才有响应。同样,之后client又需要等待约0.1秒才发送下一个数据。分析)出现上述的应答延迟的现象是程序设计的问题。当client端发送了数据后,并没有任何措施通知server端数据已经发出,需要由client的查询才能感知。此时,client端并没有放弃系统的控制权,仍然占用CPU的时间片。只有当系统进行调度时,切换到了server进程,再进行应答。这个问题,也同样存在于server端到client的应答过程之中。3.比较两种消息通信机制中的数据传输的时间由于两种机制实现的机理和用处都不一样,难以直接进行时间上的比较。如果比较其性能,应更加全面地分析。(1)消息队列的建立比共享区的设立消耗的资源少。前者只是一个软件上设定的问题,后者需要对硬件操作,实现内存的映像,当然控制起来比前者复杂。如果每次都重新进行队列或共享的建立,共享区的设立没有什么优势。(2)当消息队列和共享区建立好后,共享区的数据传输,受到了系统硬件的支持,不耗费多余的资源;而消息传递,由软件进行控制和实现,需要消耗一定的CPU资源。从这个意义上讲,共享区更适合频繁和大量的数据传输。(3)消息的传递,自身就带有同步的控制。当等到消息的时候,进程进入睡眠状态,不再消耗CPU资源。而共享队列如果不借助其他机制进行同步,接收数据的一方必须进行不断的查询,白白浪费了大量的CPU资源。可见,消息方式的使用更加灵活。二、说明:1.教材“计算机操作系统教程第二版习题解答与实验指导-张尧学”书,P90实验2,有多个错误,这正是要求同学进行分析、排错和调试,这也是考核学生的实际动手能力。一定要仔细哦。2.一定要把自己的所有程序保存在一张软盘上,以供教师检查。3.课程设计结束,要上交课程设计报告一份和含有程序的软盘一张。<完>计算机软件教研室教师:沈奕鹏管建军2006/6/20