![第2章 进程管理4-进程通信_第1页](http://file4.renrendoc.com/view/d1adf969c74d837e9d61e1bdb3b20618/d1adf969c74d837e9d61e1bdb3b206181.gif)
![第2章 进程管理4-进程通信_第2页](http://file4.renrendoc.com/view/d1adf969c74d837e9d61e1bdb3b20618/d1adf969c74d837e9d61e1bdb3b206182.gif)
![第2章 进程管理4-进程通信_第3页](http://file4.renrendoc.com/view/d1adf969c74d837e9d61e1bdb3b20618/d1adf969c74d837e9d61e1bdb3b206183.gif)
![第2章 进程管理4-进程通信_第4页](http://file4.renrendoc.com/view/d1adf969c74d837e9d61e1bdb3b20618/d1adf969c74d837e9d61e1bdb3b206184.gif)
![第2章 进程管理4-进程通信_第5页](http://file4.renrendoc.com/view/d1adf969c74d837e9d61e1bdb3b20618/d1adf969c74d837e9d61e1bdb3b206185.gif)
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
第2章进程管理本章主要内容进程的概念进程状态及转换进程控制及调度线程进程互斥与同步进程通信死锁进程通信进程通信低级通信:传递控制信号高级通信:传递数据软中断信号量共享存储区消息传递管道(文件)socket直接:消息缓冲队列间接:信箱在进程之间进行信息交换,包括传递信号和数据。请自行阅读教材P55-58关于进程通信的一般性介绍Linux进程s通信4软中断机制信号量机制(略)无名管道机制消息队列机制共享存储区机制Linux软中断通信5软中断是对硬件中断的一种模拟。发送软中断就是向接收进程的task_struct结构中的相应项发送一个信号。接收进程在收到软中断信号后,将按照事先的规定去执行一个软中断处理程序。软中断号发送后不会立即调相应处理程序,而是必须等到接收进程执行时才生效。进程也可以给自己发送软中断信号,以便在某些特殊情况下能转入规定好的处理程序。6Linux软中断信号Linux常见软中断信号类型,可以使用kill-l
查看。7格式:signal(sig,function)sig—系统给定的软中断信号中的序号或名称function—与软中断信号关联的处理函数名,当进程在运行过程中捕捉到指定的软中断信号后,中断当前程序的执行转到该函数执行。注意:软中断信号必须提前预置,然后才可以在程序运行中捕获。软中断信号预置函数signal()8格式:intkill(pid,sig)pid—进程(组)标识符:当pid>0时,将信号发给指定pid的进程;当pid=0时,将信号发给同组所有进程;当pid=-1时,将信号发给内存所有进程;当pid<0时,将信号发给进程组识别码为|pid|的所有进程。sig—软中断信号的序号或名称功能:向指定进程发软中断信号sig头文件:<sys/types.h>,<signal.h>发送软中断信号函数kill9[例1]编一程序实现循环显示字符串“Hello!”,当键盘键入Ctrl+C时终止循环,显示“OK!”后结束。分析:Ctrl+C对应的软中断信号SIGINT(序号为2),对应处理函数需终止循环显示。软中断例1intk=1;voidmain(void){while(k==1)printf("Hello!\n");//等待键入Ctrl+Cprintf(“OK!\n”); }#include<signal.h>voidint_func(intsig) //软中断处理函数{k=0;}{signal(SIGINT,int_func);//预置软中断信号处理函数}10软中断例2[例2]使用软中断实现父子进程同步,父进程先输出A,然后子进程输出B。#include<signal.h>intk=1;voidfunc(intsig){k=0;}main(){intpid;pid=fork();if(pid>0){printf("A\n");kill(pid,12);}elseif(pid==0){signal(12,func);while(k==1)
sleep(1);
printf("B\n");}}非软中断方式main(){intpid;pid=fork();if(pid>0){printf("A\n");wait(0);}elseif(pid==0){printf("B\n");}}Linux无名管道通信若只触发某些行为,软中断信号机制简捷有效。若进程间需交换数据?----管道管道:用“管道”将读写进程连接在一起,写进程将数据从写入端写入,读进程将数据从读出端读出。数据量大小是系统定义的最大缓冲区字节数。系统调用接口write(pipeID[1],buf_out,size)read(pipeID[0],buf_in,size)进程A地址空间进程B地址空间输出缓冲buf_out输入缓冲buf_in管道文件创建和使用无名管道的系统调用1.创建管道格式:intpipe(intfp[2]);返回:0---正确返回,-1----错误返回参数:fp[1]为写入端,fp[0]为读出端功能:创建一个无名管道fp,fp[1]用于写,fp[0]用于读。2.读写管道----借助文件机制格式:写管道
write(fp[1],buf,size);
读管道
read(fp[0],buf,size);参数:buf为数据缓冲区;size为l读写长度。头文件:<unistd.h>管道通信示例1main(){intp1,fd[2];charoutpipe[50],inpipe[50]=“Thisisamessagefromchild.”;
pipe(fd); p1=fork();if(p1==0)
write(fd[1],inpipe,50); //写信息到管道
elseif(p1>0);
{wait(0);//等待子进程终止
read(fd[0],outpipe,50);//从管道读信息printf("%s\n",outpipe);}}父进程创建一个子进程和一个无名管道fd,子进程向管道写入“Thisisamessagefromchild!”后终止;父进程接收到子进程终止信号后从管道中读出并显示信息后结束。管道通信示例2main(){intp1,fd[2];charstr1[50],str2[50];
pipe(fd); p1=fork();
子进程执行的分支父进程执行的分支}父进程创建一个子进程和一个无名管道fd,子进程通过管道向父进程发送“Howareyou?”,父进程接收到消息后通过管道回送“Iamfine.”,父子进程将各自收到的消息显示出来。elseif(p1>0)
{read(fd[0],str1,50);printf(“Parentreceived:%s\n”,str1);strcpy(str2,”Iamfine.”);write(fd[1],str2,strlen(str2));}if(p1==0)
{strcpy(str1,”Howareyou?”);write(fd[1],str1,strlen(str1));
read(fd[0],str2,50);printf(“Childreceived:%s\n”,str2);}管道通信示例2执行结果分析父进程读不到数据被阻塞了子进程把自己写入管道的数据读出来了!修改管道通信示例2
若将子进程执行分析修改为:
if(p1==0)
{strcpy(str1,”Howareyou?”);write(fd[1],str1,strlen(str1));
sleep(1);
read(fd[0],str2,50);printf(“Childreceived:%s\n”,str2);}父进程不变:elseif(p1>0)
{read(fd[0],str1,50);printf(“Parentreceived:%s\n”,str1);strcpy(str2,”Iamfine.”);write(fd[1],str2,strlen(str2));}请分析上述代码执行结果:先调度到父进程?先调度到子进程?无名管道通信机制特点管道中的数据是字符流,工作于单向通信方式;管道逻辑上是由系统在内存中创建的临时文件实现的,物理上则由文件系统的高速缓冲区构成;无名管道只能供创建管道的进程及其子孙进程共享;管道为临界资源,各进程对管道的访问既有同步又有互斥,需要用户自己借助同步互斥机制以及文件机制来实现对管道的访问!Linux消息缓冲队列msg_queue链表----系统所有消息队列等待发送进程pid等待接收进程pid
……msg_msg*nextmsg_msg*nextmsgbufmsgbuf……………………iker_ipc_permkey……q_messagesq_receiversq_sanders一个msg_queue结构对应一个消息队列msg结构消息队列有一个称为关键字(key)的名字;收发消息前必须创建消息队列,使用消息队列描述符(msqid)来标识该消息队列。Linux消息队列系统调用19intmsgget(key_tkey,intmsgflg);intmsgctl(intmsqid,intcmd,structmsqid_ds*buf);intmsgsnd(intmsqid,structmsgbuf*msgp,size_tmsgsz,intmsgflg);sszie_tmsgrcv(intmsqid,structmsgbuf*msgp,size_tmsgsz,longmsg_typ,intmsgflg);相关头文件:<sys/types.h>,<sys/ipc.h>,<sys/msg.h>,<stdio.h>
1.创建或获取消息队列格式:intmsgget(key_tkey,intmsgflag);功能:创建或获取标识为key的消息队列,并返回队列描述符。返回:正确返回该消息队列的描述符msgid;错误返回-1。参数:key—消息队列标识符,为正整数。可由用户指定(适用于不同进程家族);也可使用IPC_PRIVATE由系统产生key值(适用于同一进程家族);msgflag—标志或访问方式,由操作权限和控制命令进行或运算得到。操作权限:用户可读0400 小组可读0040其他可读0004 用户可写0200小组可写0020其他可写0002控制命令:IPC_CREAT(值0001000),若队列不存在则创建。21/*有关头文件…..*/main(){ intqid; key_tkey=113;
qid=msgget(key,IPC_CREAT|0666);//创建消息队列 if(qid<0) {perror("msgget");exit(1); } printf("createdqueueid:%d\n",qid); system("ipcs-q");//查看系统IPC的状态}创建消息队列示例2.对消息队列的控制格式:intmsgctl(intmsgid,intcmd,structmsqid_ds*buf);功能:查询、设置消息队列的状态;撤消消息队列。返回:函数调用成功返回0,不成功返回-1。参数:msgid—该消息队列的描述符;cmd—规定命令的类型:IPC_STAT查询消息队列状态,将消息队列的msqid_ds复制到buf;IPC_SET设置或修改消息队列状态,设置有效用户、组标识、操作允许权、字节数;IPC_RMID撤消描述符为msgid的消息队列;buf—含有控制参数或查询结果的用户缓冲区的地址,可为0。/*有关头文件…..*/main(){ intqid; intkey=113;
qid=msgget(key,IPC_CREAT|0666);//创建消息队列
if(qid<0) {perror("msgget");exit(1); } printf("createdqueueid:%d\n",qid); system(“ipcs-q”);//查看系统IPC的状态 if(msgctl(qid,IPC_RMID,NULL)<0) {perror(“msgctl”);exit(1);} system("ipcs-q"); printf("successfullyremoved%dqueue\n",qid);}删除消息队列示例3.发送消息格式:intmsgsnd(intmsgid,structmsgbuf*msgp,intsize,intflag);功能:将msgp->msgbuf中的消息复制到msgid消息队列中,将之挂到队尾,唤醒等待消息的进程。参数:msgid—执行msgget()返回的消息队列的描述符;msgp—待发送的消息;size—由msgp指向的数据结构中消息长度;flag—规定当消息队列满时应执行的动作,例如:若在flag中设置了IPC_NOWAIT,则当消息队列中的字节数超过最大值时,msgsnd立即返回,否则msgsnd睡眠。flag可置0。25/*有关头文件…..*/structmsg{longmtype;//消息类型charmtext[511];//消息正文};intmain(void){intqid,pid;structmsgpmsg;//创建消息队列
qid=msgget(113,IPC_CREAT|0666)if(qid<0){perror("msgget");exit(1);}system(“ipcs-q”);发送消息示例//发送消息到队列上pmsg.mtype=getpid();sprintf(pmsg.mtext,"hello!thisis%d\n\0",getpid());
if(msgsnd(qid,&pmsg,len,0)<0){perror("msgsnd");exit(1);}system(“ipcs-q”);//删除消息队列if(msgctl(qid,IPC_RMID,NULL)<0){perror(“msgctl”);exit(1);}system("ipcs-q");printf("successfullyremoved%dqueue\n",qid);}4.接收消息格式:intmsgrcv(intmsgid,structmsgbuf*msgp,intsize,inttype,intflag);功能:从msgid消息队列中接收一个消息:将消息复制到msgp->msgbuf中,并从队列中删除此消息,若消息未到则调用进程阻塞插入等待消息队列尾。参数:msgid—消息队列描述符;msgp—存放接收消息的用户缓冲区的首地址;size—要接收字节数(一般为msgp中数据数组的大小);type—接收消息类型:=0--接收队列的第一个消息;>0--接收类型为type的第一个消息;<0—接收第一个类型小于或等于|type|的消息。flag—若该队列无消息,内核应当做什么,可置0。IPC_NOWAIT,立即返回IPC_EXCEPT与msgtype>0配合使用,返回队列中第一个类型不为msgtype的消息IPC_NOERROR
如果消息内容大于所请求的字节,则丢弃多余字节。#include<sys/msg.h>structmsg{longmtype;charmtext[256];}pmsg;main(){intmsgqid,pid;msgqid=msgget(75,0777);printf(“msgid:%d\n”,msgqid);pmsg.mtype=1;*((int*)pmsg.text)=getpid();msgsnd(msgqid,&pmsg,sizeof(int),0);msgrcv(msgqid,&pmsg,256,getpid(),0);printf(“A:receivemsgfrom%d\n",
*((int*)pmsg.text));}27消息通信示例—模拟服务器与客户端进程A发送如下消息给进程B:mtypemtext1A_pid进程B等待接收A的消息并回送如下消息:mtypemtextA_pidB_pid#include<sys/msg.h>intmsgqid,pid;structmsg{longmtype;charmtext[256];}pmsg;cancelqueue(){msgctl(msgqid,IPC_RMID,0);exit(0);}main(){signal(2,cancelqueue); msgqid=msgget(75,0777|IPC_CREAT);while(1){msgrcv(msgqid,&pmsg,256,1,0);pid=*(int*)pmsg.mtext;printf(“B:receivemsgfrom%d\n",pid);pmsg.mtype=pid;*((int*)pmsg.text)=getpid();msgsnd(msgqid,&pmsg,sizeof(int),0);}}没有IPC_CREAT,只获取不创建28消息通信示例—模拟服务器与客户端运行结果29Linux共享存储区通信消息缓冲需要CPU复制消息,进程间直接进行数据交换的通信方式?——共享内存附接附接进程A地址空间进程B地址空间共享内存与消息缓冲通信类似,Linux对共享内存通信也提供了4个系统调用函数:shmget()
shmat()shmdt()shmctl()头文件:
sys/types.h,linux/shm.h共享存储区系统调用1.创建或获取一个共享内存格式:intshmid=shmget(key_tkey,intsize,intflag);功能:获得一个内部标识为shmid的共享存储区参数:key—共享存储区关键字,由用户指定或由系统产生(IPC_PRIVATE)。size—存储区的字节数。flag—标志或访问方式,与shmget中含义相同,如0666|IPC_CREAT表示任意进程可读可写。返回:正确时返回共享存储区的标识符shmid,错误则返回-1。2.将共享内存附接到进程的虚拟地址空间格式:void*shmat(intshmid,void*shmaddr,intflag);功能:将shmid共享存储区附接到进程的虚拟地址空间shmaddr。参数:shmid—共享存储区的描述符,由shmget()的返回值得到;shmaddr—共享存储区附接的虚地址,若shmaddr为0,则由系统选择一个适当的地址来附接该存储区;flag—存储区的操作权限以及系统是否要舍除用户规定的地址。SHM_RND表示在必要时舍去地址;SHM_RDONLY表示只读,flag为0表示可读可写;返回值—正确返回附接的虚地址;出错返回-1。调用举例:字符型:char*viraddr=(char*)shmat(shmid,shmaddr,shmflag);数值型:int*viraddr=(int*)shmat(shmid,shmaddr,shmflag);3.将共享内存从进程的地址空间断开(断接)格式:shmdt(viraddr);功能:将一个共享存储区从指定进程的虚拟地址空间断开参数:viraddr——系统调用shmat()所返回的虚地址返回:正确返回0
错误返回-14.对共享内存的控制或查询格式:shmctl(intshmid,intcmd,structshmid_ds*buf)功能:对共享存储区进行控制,如删除共享存储区。返回值:正确返回0,错误返回-1。参数:shmid—共享存储区的内部标识符,由shmget()调用返回;buf—读写共享存储区参数的数据缓冲区,可为0。cmd—操作类型:
IPC_STAT---返回包相关数据结构中的状态信息,由buf带出
IPC_SET---设置有效用户和小组标识符和操作存取权,由buf带入
IPC_RMID---删除共享存储区
SHM_LOCK---锁定共享存储区,须是超级用户才可操作。调用举例:shmctl(shmid,IPC_RMID,0);共享内存通信实现方法:发送进程1.用shmget()创建或者获取指定key值的共享内存;2.用shmat()将该共享内存附接到自己的虚拟地址空间;3.将需要发送的信息写入共享内存:①共享内存定义为字符串,则可通过strcat(viraddr,buf)将buf追加到共享存储区尾部。或通过strcpy(viraddr,buf)将buf复制到共享内存中。②共享内存定义为单变量,则可将*viraddr作为数值型变量对其进行操作。如*viradd=0。③共享内存定义为数组变量,则可将viraddr[i]作为下标变量使用。如viradd[i]=0。4.使用shmdt()
断开共享内存。5.如果不再使用共享内存时,用shmctl()将其撤消,格式为:shmctl(shmid,IPC_RMID,0);
共享内存通信实现方法:接收进程1.用shmget()创建或者获取指定key值的共享内存;2.用shmat()将该共享内存附接到自己的程序空间;3.读取共享内存中的信息;4.用shmdt()断开共享内存。5.如果不再使用共享内存时,用shmctl()将其撤消,格式为:shmctl(shmid,IPC_RMID,0);共享内存通信示例#include<stdio.h>#include<linux/shm.h>main(){ intshmid; char*va,buf[BUFSIZ];
shmid=shmget(22,BUFSIZ,0666|IPC_CREAT);
va=(char*)shmat(shmid,0,0);while(1)
{puts("Entersometext:");fgets(buf,BUFSIZ,stdin);
strcat(va,buf);
if(strncmp(buf,"end",3)==0)break; }
shmdt(va);//断开附接
shmctl(shmid,IPC_RMID,0);
}/*头文件*/main(){intshmid;char*va;shmid=shmget(22,BUFSIZ,0666|IPC_CREAT);va=(char*)shmat(shmid,0,0);printf("Yourmsgis:%s\n",va);shmdt(va);
}发送程序shma.c接收程序shmb.c共享内存通信特点共享内存只能由处于同一个计算机系统中的诸进程共享。进程之间的读写操作的同步问题必须由诸共享该内存的进程去控制。信号量机制基本PV原语原理。Linux提供下列3个有关信号量的系统调用函数:semget()semop()semctl()头文件:sys/ipc.h,sys/sem.h信号量机制格式:intsemget(key_tkey,intnsems,intsemflg);返回:正确返回信号量集的标识符,错误返回-1参数:key——信号量集的key值,使用IPC_PRIVATE由系统产生key值,或由用户指定一个正整数。nsems——指定信号量集中信号量数目,最大值在linux/sem.h中定义:#defineSEMMSL250/*<=8000*/semflg——当key值不为IPC_PRIVATE:①.只设置semflag的IPC_CREAT位,则创建一个信号量集,若该信号量集已存在,则返回其标识符②.设置semflag的IPC_CREAT|IPC_EXCL位,则创建一个新的信号量集,若信号量集已存在则返回错误信息。③.只设置IPC_EXCL位而不设置IPC_CREAT位没有意义。调用举例:semid=semget(SEMKEY,2,0777|IPC_CREAT);1
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 2025年度智能仓储卷帘门系统采购及集成合同
- 2025年度区块链技术应用项目开发与许可合同
- 2025年休假村租赁协议模板
- 2025年建筑工程模板工程承包合同书
- 2025年信用卡债务履行协议
- 2025年金刚石膜工具项目立项申请报告模范
- 2025年血液系统用药项目规划申请报告模范
- 2025年街头篮球项目规划申请报告
- 2025年放射性药品项目提案报告模式
- 2025年生活用橡胶制品:塑胶盒项目规划申请报告范文
- 2022人脸识别安全白皮书
- 【建模教程】-地质统计学矿体建模简明教材
- 无人机应用案例-石油领域油气管线巡查
- DB23T 2656-2020桦树液采集技术规程
- 重源煤矿 矿业权价款计算书
- PSM工艺安全管理
- GB/T 21872-2008铸造自硬呋喃树脂用磺酸固化剂
- 上海市中小学生语文学业质量绿色指标测试
- GA/T 501-2020银行保管箱
- 《育儿百科》松田道雄(最新版)
- 轴对称图形导学案
评论
0/150
提交评论