实验三2Linux进程间通信.docx
- 文档编号:549405
- 上传时间:2022-10-11
- 格式:DOCX
- 页数:7
- 大小:18.14KB
实验三2Linux进程间通信.docx
《实验三2Linux进程间通信.docx》由会员分享,可在线阅读,更多相关《实验三2Linux进程间通信.docx(7页珍藏版)》请在冰豆网上搜索。
实验三2Linux进程间通信
实验三2_Linux进程间通信
实验三Linux进程间通信
一、实验目的
熟悉Linux下进程间通信机制,能够使用系统提供的各种通信机制实现并发进程间的数据交换。
二、实验题目
分别使用Linux下的共享存储区、消息、管道等通信机制,编程实现并发进程之间的相互通信。
三、背景材料
(一)需要用到的系统调用
实验可能需要用到的主要系统调用和库函数在下面列出,详细的使用方法说明通过“man2系统调用名”或者“man3函数名”命令获取。
fork()创建一个子进程,通过返回值区分是在父进程还是子进程中执行;
wait()等待子进程执行完成;
getpid()获取当前进程id;
shmget()建立一个共享存储区;
shmctl()操纵一个共享存储区;
shmat()把一个共享存储区附接到进程内存空间;
shmdt()把一个已经附接的共享存储区从进程内存空间断开;
msgget()建立一个消息队列;
msgctl()操纵一个消息队列;
msgsnd()发送消息;
msgrcv()接收消息;
signal()设置对信号的处理方式或处理过程;
pipe()打开管道;
lockf()锁定一个文件。
(二)使用共享存储区的示例程序
下面程序主要用来演示共享存储区的使用方法:
首先要使用shmget得到共享存储区句柄(可以新建或连接已有的共享存储区,以关键字标识),然后使用shmat挂接到进程的存储空间(这样才能够访问),当使用完后,使用shmctl释放(shmctl还可以完成一些其他功能)。
这种使用逻辑也适用于消息和信号量。
示例程序代码如下:
#include
#include
#include
#include
#include
intmain(void)
{
intx,shmid;
int*shmptr;
if((shmid=shmget(IPC_PRIVATE,sizeof(int),IPC_CREAT|0666))<0)
printf("shmgeterror"),exit
(1);
//函数原型intshmget(key_tkey,intsize,intshmflg);函数用于创建(或者获取)一
key键值指定的共享内存对象,返回该对象的系统标识符:
shmid;size是创个由
IPC_CREAT|0666,说明新建一个权限为0666的消息队列,建的共享内存的大小,
id,若其中组用户、当前用户以及其他用户拥有读写的权限若成功则返回共享内存
-1出错则为
if((shmptr=(int*)shmat(shmid,0,0))==(int*)-1)
printf("shmaterror"),exit
(1);
//void*shmat(intshm_id,void*shm_addr,intshmflg);shm_id标识码,shm_addr连
shmflg标志位接到的地址
printf("Inputainitialvaluefor*shmptr:
");
scanf("%d",shmptr);
while((x=fork())==-1);
if(x==0)/*childrun*/
{
printf("Whenchildruns,*shmptr=%d\n",*shmptr);
printf("Inputavalueinchild:
");
scanf("%d",shmptr);
printf("*shmptr=%d\n",*shmptr);
}
else/*parentrun*/
{
wait();
printf("Afterchildruns,inparent,*shmptr=%d\n",*shmptr);
if(shmctl(shmid,IPC_RMID,0)<0)
//shmctl()函数声明:
intshmctl(intshmqid,intcmd,structshmid_ds*buf);
返回值:
0onsuccess
函数用于对已创建的共享内存对象进行查询、设值、删除等操作;这个函数-1onerror:
和msgget()函数十分相似,用法也相同。
它支持的操作有:
shm_id所指向内存共享段的shmid_dsIPC_STAT获得共享内存的信息,
结构,对参数buf指向的结构。
使用buf指向的结构对sh_mid段的相关结IPC_SET设定共享内存的信息,
构赋值,只对以下几个域有作用,shm_perm.
uidshm_perm.gid以及shm_perm.mode
注意此命令只有具备以下条件的进程才可以请求:
1(进程的用户ID等于shm_perm.cuid或者
等于shm_perm.uid
2(超级用户特权进程。
删除shm_id所指向的共享内存段,只有当IPC_RMID删除共享内存,
shmid_ds结构的shm_nattch域为零时,才
会真正执行删除命令,否则不会删除该段注意此命令的请求规则与IPC_SET命令相同。
需要说明的是,当执行IPC_RMID操作时,系统并不是立即将其删除,而只是将其标为待删,然后等待与其连接的进程断开连接。
只有当所有的连接都断开以后系统才执行真正的删除操
作。
当然,如果执行IPC_RMID的时候没有任何的连接,删除将是立即的。
printf("shmctlerror"),exit
(1);
}
}
(三)使用消息机制的示例程序
示例程序执行的进程分为两种,分别称为服务进程和客户进程:
服务进程只有一个,接收各客户进程以消息形式发出的问题,接收键盘输入作为回答,再以消息形式送给提问的进程。
各客户进程接收键盘输入作为问题,以消息形式发给服务进程,等待接收服务进程发来的回答消息,再开始下一轮的循环。
示例程序的实际执行效果如下:
编译后执行,第一个进程实例将作为服务进程,提示:
ACTSERVER!
!
!
Waitquestionandgiveanswer.
Toendthisprocess,tryCtrl+Corusekill.
服务进程一直循环执行,直到用户按Ctrl+C终止执行,或使用kill命令杀死服务进程。
其他进程实例作为客户进程,提示:
Actasclient,askquestionandwaitanswer!
Toendthisprocess,enterendasinputquestion.
客户进程一直循环执行,直到用户输入end。
示例程序的代码如下:
#include
#include
#include
#include
#include
#include
#include
#defineMY_KEY10071140//needtochange
#defineSERVER_ID2
#defineMAX_BUF200
voidsigend(int);
structmymsg{
longmtype;
longpid;
charbuf[MAX_BUF];
};
intmsgid;
intmain(void)
{
structmymsgmsgbuf;
if((msgid=msgget(MY_KEY,IPC_CREAT|IPC_EXCL|0666))<0)
//intmsgget(key_tkey,intflags);函数中参数key用来转换成一个标识符,每一
IPC对象与一个key相对应。
参数flags标明函数的行为,函数中参数falgs指定个
IPC_CREAT|0666,说明新建一个权限为0666的消息队列,其中组用户、当前用为
户以及其他用户拥有读写的权限
{/*messagequeueexists,actasclient*/
msgid=msgget(MY_KEY,0666);
printf("Actasclient,askquestionandwaitanswer!
\n");
printf("Toendthisprocess,enterendasinputquestion.\n\n");
printf("Inputquestioninoneline:
\n");
fgets(msgbuf.buf,sizeof(structmymsg)-2*sizeof(long)-1,stdin);
//fgets:
从流中读取一字符串,char*fgets(char*string,intn,FILE*stream);
形参注释:
*string结果数据的首地址;n-1:
一次读入数据块的长度,其默认值为1k,
1024;stream文件指针即
while(strcmp(msgbuf.buf,"end\n"))
{
msgbuf.mtype=SERVER_ID;
msgbuf.pid=getpid();
msgsnd(msgid,&msgbuf,sizeof(structmymsg)-sizeof(long),0);
//新的消息总是放在队列的尾部,函数中参数msqid指定要操作的队列,struct
msgbuf{
longmtype;
charmbuf[];
};
mbuf是一个字符数组,长度是根据具体的消息来决定的,切忌消息不能以NULL
结尾。
成员mtype是消息的类型字段。
函数参数nbytes指定了消息的长度,参数flags
指明函数的行为。
函数成功返回0,失败返回-1并设置错误变量errno。
msgrcv(msgid,&msgbuf,sizeof(structmymsg),getpid(),0);
//msgrcv(intmsqid,void*ptr,size_tnbytes,longtype,intflag);函数中参数
msqid为指定要读的队列,参数ptr为要接收数据的缓冲区,nbytes为要接收数据的
nbytes的值时,则会参照行为参数flag的长度,当队列中满足条件的消息长度大于
flag中设置了MSG_NOERROR位时,则将消息截短到nbytes值决定如何操作:
当
指定的长度后返回。
printf("Answerfromserver:
\n%s",msgbuf.buf);
printf("Inputquestioninoneline:
\n");
fgets(msgbuf.buf,sizeof(structmymsg)-2*sizeof(long)-1,stdin);
}
}
else/*actsasserver*/
{
signal(SIGINT,sigend);
//如果发生SIGINT信号则中断,转去执行sig
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 实验 Linux 进程 通信