进程的消息通信带标准答案版.docx

上传人:b****8 文档编号:11959464 上传时间:2023-06-03 格式:DOCX 页数:17 大小:101.72KB
下载 相关 举报
进程的消息通信带标准答案版.docx_第1页
第1页 / 共17页
进程的消息通信带标准答案版.docx_第2页
第2页 / 共17页
进程的消息通信带标准答案版.docx_第3页
第3页 / 共17页
进程的消息通信带标准答案版.docx_第4页
第4页 / 共17页
进程的消息通信带标准答案版.docx_第5页
第5页 / 共17页
进程的消息通信带标准答案版.docx_第6页
第6页 / 共17页
进程的消息通信带标准答案版.docx_第7页
第7页 / 共17页
进程的消息通信带标准答案版.docx_第8页
第8页 / 共17页
进程的消息通信带标准答案版.docx_第9页
第9页 / 共17页
进程的消息通信带标准答案版.docx_第10页
第10页 / 共17页
进程的消息通信带标准答案版.docx_第11页
第11页 / 共17页
进程的消息通信带标准答案版.docx_第12页
第12页 / 共17页
进程的消息通信带标准答案版.docx_第13页
第13页 / 共17页
进程的消息通信带标准答案版.docx_第14页
第14页 / 共17页
进程的消息通信带标准答案版.docx_第15页
第15页 / 共17页
进程的消息通信带标准答案版.docx_第16页
第16页 / 共17页
进程的消息通信带标准答案版.docx_第17页
第17页 / 共17页
亲,该文档总共17页,全部预览完了,如果喜欢就下载吧!
下载资源
资源描述

进程的消息通信带标准答案版.docx

《进程的消息通信带标准答案版.docx》由会员分享,可在线阅读,更多相关《进程的消息通信带标准答案版.docx(17页珍藏版)》请在冰点文库上搜索。

进程的消息通信带标准答案版.docx

进程的消息通信带标准答案版

实验二进程管理

2.2进程的消息通信

1.实验目的

(1)加深对进程通信的理解,理解进程消息传递机制。

(2)掌握进程通信相关系统调用。

(3)理解系统调用和用户命令的区别。

2.实验类型:

验证型

3.实验学时:

2

4.实验原理和知识点

(1)实验原理:

消息通信机制允许进程之间大批量交换数据。

消息通信机制是以消息队列为基础的,消息队列是消息的链表。

发送进程将消息挂入接收进程的消息队列,接收进程从消息队列中接收消息。

消息队列有一个消息描述符。

对消息队列的操作是通过描述符进行的。

任何进程,只要有访问权并且知道描述符,就可以访问消息队列。

每个消息包括一个正长整型的类型字段,和一个非负长度的数据。

进程读或写消息时,要给出消息的类型。

若队列中使用的消息类型为0,则读取队列中的第一个消息。

(2)知识点:

消息、消息队列

5.实验环境(硬件环境、软件环境):

(1)硬件环境:

IntelPentiumIII以上CPU,128MB以上内存,2GB以上硬盘

(2)软件环境:

linux操作系统。

6.预备知识

(1)msgget()系统调用:

头文件#include

函数原型intmsgget(key_tkey,intflag);

功能:

创建消息队列,或返回与key对应的队列描述符。

成功返回消息描述符,失败则返回-1。

参数:

key是通信双方约定的队列关键字,为长整型数。

flag是访问控制命令,它的低9位为访问权限(代表用户、组用户、其他用户的读、写、执行访问权),其它位为队列建立方式。

(例:

rwxrwx---:

111111000)

(2)msgsnd()系统调用:

头文件#include

函数原型intmsgsnd(intid,structmsgbuf*msgp,intsize,intflag);

功能:

发送一个消息。

成功返回0,失败返回-1。

参数:

id是队列描述符。

msgp是用户定义的缓冲区。

size是消息长度。

flag是操作行为,若(flag&IPC_NOWAIT)为真,调用进程立即返回;若(flag&IPC_NOWAIT)为假,调用进程阻塞,直到消息被发送出去或队列描述符被删除或收到中断信号为止。

缓冲区结构定义如下:

structmsgbuf{longmtype;charmtext[n];};

(3)msgrcv()系统调用:

头文件#include

函数原型intmsgrcv(intid,structmsgbuf*msgp,intsize,inttype,intflag);

功能:

接收一个消息。

成功返回消息正文长度,失败返回-1。

参数:

id是队列描述符。

msgp是用户定义的缓冲区。

size是要接收的消息长度。

type是消息类型,若type为0则接收队列中的第一个消息,若type为正则接收类型为type的第一个消息。

flag是操作行为,若(flag&IPC_NOWAIT)为真,调用进程立即返回。

若(flag&IPC_NOWAIT)为假,调用进程睡眠,直到接收到消息为止。

(4)msgctl()系统调用:

头文件#include

函数原型intmsgctl(intid,intcmd,structmsgid_ds*buf);

功能:

查询消息队列描述符状态,或设置描述符状态,或删除描述符。

成功返回0,失败返回-1。

参数:

id是队列描述符。

cmd是命令类型,若cmd为IPC_STAT,队列id的消息队列头结构读入buf中;若cmd为IPC_SET,把buf所指向的信息复制到id的消息队列头结构中。

若cmd为IPC_RMID,删除id的消息队列。

Buf为消息队列头结构msgid_ds指针。

(linuxIPC

7.实验内容及步骤:

(1)任务描述:

使用系统调用msgget()、msgsnd()、msgrcv()、msgctl(),编写消息发送和接收程序。

要求消息的长度为1KB。

(2)程序设计过程:

先定义消息结构,

structmsgbuf{

longmtype;

charmtext[n];

};

用这个结构定义消息缓冲全局变量msg。

定义消息队列描述符msgqid。

约定队列关键字为75。

创建两个子进程client和server。

Client使用msgget()创建消息队列,使用msgsnd()发送10条消息。

Server使用msgget()获取消息队列描述符,然后用msgrcv()接收消息,完毕后删除队列描述符。

为了清楚地显示Client发送的是哪条消息,每发送一条消息,打印消息号(消息类型),Sever每收到一条消息,也打印消息类型。

设计收发方式。

Client每发送一条,Sever就接收一条。

/*收发方式:

Client()每发送一条消息,Server()就接收一条*/

/*此方法不能保证一定能同步。

对于不同速度的机器,如果没有其他耗时的进程,可以调整sleep的时间值而获得同步。

*/

//msg.c

#include

#include

#include

#include

#defineMSGKEY75/*通信双方约定的队列关键字*/

structmsgform/*消息结构*/

{longmtype;/*消息类型*/

charmtext[1030];/*消息正文*/

}msg;

intmsgqid;/*消息队列描述符*/

voidClient()

{inti;/*局部变量i,消息类型(表示第几条消息)*/

msgqid=msgget(MSGKEY,0777);/*创建消息队列,访问权限为777*/

for(i=10;i>=1;i--)

{msg.mtype=i;/*指定消息类型*/

printf("(client%d)sent.\n",i);/*打印消息类型*/

msgsnd(msgqid,&msg,1024,0);

/*发送消息msg到msgqid消息队列,可以先把消息正文放到msg.mtext中*/

sleep

(1);/*使进程挂起1秒。

等待接收进程接收。

比较加上这一句和不加这一句的结果*/

}

exit(0);

}

voidServer()

{/*获得关键字对应的消息队列描述符*/

msgqid=msgget(MSGKEY,0777|IPC_CREAT);

do{

msgrcv(msgqid,&msg,1030,0,0);/*从msgqid队列接收消息msg*/

printf("(server%d)received.\n",msg.mtype);/*打印消息类型*/

}while(msg.mtype!

=1);/*消息类型为1时,释放队列*/

msgctl(msgqid,IPC_RMID,0);/*删除消息队列*/

exit(0);

}

voidmain()

{inti;

while((i=fork())==-1);/*创建子进程;如果创建失败,执行空语句*/

if(!

i)Server();/*如果i=0,在子进程中,运行Server*/

else/*否则,在父进程中*/

{while((i=fork())==-1);/*继续创建子进程*/

if(!

i)Client();/*如果i=0,在子进程中,运行Client*/

}

wait(0);/*等待子进程结束*/

wait(0);/*等待子进程结束*/

}

注:

IPC进程间通信(Inter-ProcessCommunication)就是指多个进程之间相互通信,交换信息的方法。

(3)上机操作

创建msg.c源文件,编译gcc–omsgmsg.c,运行./msg

观察屏幕,记录结果。

简答:

程序中有,sleep

(1);/*使进程挂起1秒。

等待接收进程接收。

比较加上这一句和不加这一句的结果*/,试分析为什么会有这样的运行结果差异。

 

(4)课堂练习

(1)修改上述程序,让Client向Server发送一个字符串“Themessagehereisjustajoke.”。

Server收到消息后打印出来。

参考答案:

//msg2.c

#include

#include

#include

#include

#defineMSGKEY75/*通信双方约定的队列关键字*/

structmsgform/*消息结构*/

{longmtype;/*消息类型*/

charmtext[1024];/*消息正文*/

}msg;

intmsgqid;/*消息队列描述符*/

voidClient()

{msg.mtype=1;

strcpy(msg.mtext,"Themessagehereisjustajoke.");

msgqid=msgget(MSGKEY,0777);/*创建消息队列,访问权限为777*/

/*指定消息类型*/

printf("(client1)sent.\n");/*打印消息类型*/

msgsnd(msgqid,&msg,strlen(msg.mtext),0);

/*发送消息msg到msgqid消息队列,可以先把消息正文放到msg.mtext中,strlen(msg.mtext)*/

exit(0);

}

voidServer()

{/*获得关键字对应的消息队列描述符*/

msgqid=msgget(MSGKEY,0777|IPC_CREAT);

msgrcv(msgqid,&msg,1024,0,0);/*从msgqid队列接收消息msg*/

printf("(server1)received.\n");/*打印消息类型*/

printf("%s\n",msg.mtext);/*消息类型为1时,释放队列*/

msgctl(msgqid,IPC_RMID,0);/*删除消息队列*/

exit(0);

}

voidmain()

{inti;

while((i=fork())==-1);/*创建子进程*/

if(!

i)Server();/*子进程Server*/

else

{while((i=fork())==-1);/*创建子进程*/

if(!

i)Client();/*子进程Client*/

}

wait(0);/*等待子进程结束*/

wait(0);/*等待子进程结束*/

}

(5)思考:

1、进程的消息传递机制和全局变量是一个概念吗?

消息是通过全局变量进行传递的吗?

//msg2.c

#include

#include

#include

#include

#defineMSGKEY75/*通信双方约定的队列关键字*/

structmsgform/*消息结构*/

{longmtype;/*消息类型*/

charmtext[1024];/*消息正文*/

}msg;

intmsgqid;/*消息队列描述符*/

voidClient()

{printf("starcopy\n");

strcpy(msg.mtext,"Themessagehereisjustajoke.");

printf("endcopy\n");

exit(0);

}

voidServer()

{

sleep

(1);

printf("stardisplay\n");

printf("done!

%s\n",msg.mtext);

printf("endcopy\n");

exit(0);

}

voidmain()

{inti;

while((i=fork())==-1);/*创建子进程*/

if(!

i)Server();/*子进程Server*/

else

{while((i=fork())==-1);/*创建子进程*/

if(!

i)Client();/*子进程Client*/

}

wait(0);/*等待子进程结束*/

wait(0);/*等待子进程结束*/

}

1.在client里面改变了msg.mtext,但是server里面printf出来却什么也没有,说明全局变量不可在进程间传递信息。

//msg2.c

#include

#include

#include

#include

#defineMSGKEY75/*通信双方约定的队列关键字*/

structmsgform/*消息结构*/

{longmtype;/*消息类型*/

charmtext[1024];/*消息正文*/

}msg;

intmsgqid;/*消息队列描述符*/

voidClient()

{sleep

(1);

printf("clientrunning!

\n");

exit(0);

}

voidServer()

{

sleep

(2);

printf("stardisplay\n");

printf("done!

%s\n",msg.mtext);

printf("endcopy\n");

exit(0);

}

voidmain()

{

printf("starcopy\n");

strcpy(msg.mtext,"Themessagehereisjustajoke.");

printf("endcopy\n");

inti;

while((i=fork())==-1);/*创建子进程*/

if(!

i)Server();/*子进程Server*/

else

{while((i=fork())==-1);/*创建子进程*/

if(!

i)Client();/*子进程Client*/

}

wait(0);/*等待子进程结束*/

wait(0);/*等待子进程结束*/

}

2.在主函数里面改变全局变量是可以传递消息的,因为这是父进程,server是子进程,子进程继承父进程的全部代码和资源。

3.换个位置又不行了哦,想想是为什么!

有没有晕了呢!

//msg2.c

#include

#include

#include

#include

#defineMSGKEY75/*通信双方约定的队列关键字*/

structmsgform/*消息结构*/

{longmtype;/*消息类型*/

charmtext[1024];/*消息正文*/

}msg;

intmsgqid;/*消息队列描述符*/

voidClient()

{sleep

(1);

printf("clientrunning!

\n");

exit(0);

}

voidServer()

{

sleep

(2);

printf("stardisplay\n");

printf("done!

%s\n",msg.mtext);

printf("endcopy\n");

exit(0);

}

voidmain()

{

inti;

while((i=fork())==-1);/*创建子进程*/

if(!

i)Server();/*子进程Server*/

else

{while((i=fork())==-1);/*创建子进程*/

if(!

i){

printf("starcopy\n");

strcpy(msg.mtext,"Themessagehereisjustajoke.");

printf("endcopy\n");

Client();}/*子进程Client*/

}

wait(0);/*等待子进程结束*/

wait(0);/*等待子进程结束*/

}

简单的说,不同的进程使用的内存空间是不共用的,全局变量只是在同一个进程所占用的内存空间中是全局变量,而其他的进程空间是根本看不到这个变量的。

父子进程不共享数据空间、堆、和栈。

所以不存在共享全局变量。

进程间只能IPC。

2、修改上述程序,让Client向Server发送两个字符串“Themessagehereisjustajoke.”。

Server收到消息后打印出来。

效果图如下。

//msg2.c

#include

#include

#include

#include

#defineMSGKEY75/*通信双方约定的队列关键字*/

structmsgform/*消息结构*/

{longmtype;/*消息类型*/

charmtext[1024];/*消息正文*/

}msg;

intmsgqid;/*消息队列描述符*/

voidClient()

{msgqid=msgget(MSGKEY,0777);/*创建消息队列,访问权限为777*/

/*指定消息类型*/

//消息1发送

msg.mtype=1;

strcpy(msg.mtext,"Thankyou.");

printf("(client1)sent.\n");/*打印消息类型*/

msgsnd(msgqid,&msg,strlen(msg.mtext),0);

/*发送消息msg到msgqid消息队列,可以先把消息正文放到msg.mtext中,strlen(msg.mtext)*/

//消息2发送

msg.mtype=2;

strcpy(msg.mtext,"Themessagehereisjustajoke.");

printf("(client2)sent.\n");/*打印消息类型*/

msgsnd(msgqid,&msg,strlen(msg.mtext),0);

/*发送消息msg到msgqid消息队列,可以先把消息正文放到msg.mtext中,strlen(msg.mtext)*/

exit(0);

}

voidServer()

{/*获得关键字对应的消息队列描述符*/

msgqid=msgget(MSGKEY,0777|IPC_CREAT);

//接收消息1

msgrcv(msgqid,&msg,1024,1,0);/*从msgqid队列接收消息msg*/

printf("(server1)received.\n");/*打印消息类型*/

printf("%s\n",msg.mtext);/*消息类型为1时,释放队列*/

//接收消息2

msgrcv(msgqid,&msg,1024,2,0);/*从msgqid队列接收消息msg*/

printf("(server2)received.\n");/*打印消息类型*/

printf("%s\n",msg.mtext);/*消息类型为2时,释放队列*/

msgctl(msgqid,IPC_RMID,0);/*删除消息队列*/

exit(0);

}

voidmain()

{inti;

while((i=fork())==-1);/*创建子进程*/

if(!

i)Server();/*子进程Server*/

else

{while((i=fork())==-1);/*创建子进程*/

if(!

i)Client();/*子进程Client*/

}

wait(0);/*等待子进程结束*/

wait(0);/*等待子进程结束*/

}

展开阅读全文
相关资源
猜你喜欢
相关搜索
资源标签

当前位置:首页 > 经管营销 > 经济市场

copyright@ 2008-2023 冰点文库 网站版权所有

经营许可证编号:鄂ICP备19020893号-2