第2章 进程管理4-进程通信_第1页
第2章 进程管理4-进程通信_第2页
第2章 进程管理4-进程通信_第3页
第2章 进程管理4-进程通信_第4页
第2章 进程管理4-进程通信_第5页
已阅读5页,还剩40页未读 继续免费阅读

下载本文档

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

文档简介

1、第2章进程管理,本章主要内容,进程的概念进程状态及转换进程控制及调度线程进程互斥与同步进程通信死锁,进程通信,在进程之间进行信息交换,包括传递信号和数据。,请自行阅读教材P55-58关于进程通信的一般性介绍,Linux进程s通信,4,软中断机制信号量机制(略)无名管道机制消息队列机制共享存储区机制,Linux软中断通信,5,软中断是对硬件中断的一种模拟。发送软中断就是向接收进程的task_struct结构中的相应项发送一个信号。接收进程在收到软中断信号后,将按照事先的规定去执行一个软中断处理程序。软中断号发送后不会立即调相应处理程序,而是必须等到接收进程执行时才生效。进程也可以给自己发送软中断

2、信号,以便在某些特殊情况下能转入规定好的处理程序。,6,Linux软中断信号,Linux常见软中断信号类型,可以使用kill-l查看。,7,格式:signal(sig,function)sig系统给定的软中断信号中的序号或名称function与软中断信号关联的处理函数名,当进程在运行过程中捕捉到指定的软中断信号后,中断当前程序的执行转到该函数执行。注意:软中断信号必须提前预置,然后才可以在程序运行中捕获。,软中断信号预置函数signal(),8,格式:intkill(pid,sig)pid进程(组)标识符:当pid0时,将信号发给指定pid的进程;当pid=0时,将信号发给同组所有进程;当pi

3、d=-1时,将信号发给内存所有进程;当pid,发送软中断信号函数kill,9,例1编一程序实现循环显示字符串“Hello!”,当键盘键入Ctrl+C时终止循环,显示“OK!”后结束。分析:Ctrl+C对应的软中断信号SIGINT(序号为2),对应处理函数需终止循环显示。,软中断例1,intk=1;voidmain(void)while(k=1)printf(Hello!n);/等待键入Ctrl+Cprintf(“OK!n”);,#includevoidint_func(intsig)/软中断处理函数k=0;signal(SIGINT,int_func);/预置软中断信号处理函数,10,软中断例

4、2,例2使用软中断实现父子进程同步,父进程先输出A,然后子进程输出B。,#includeintk=1;voidfunc(intsig)k=0;main()intpid;pid=fork();if(pid0)printf(An);kill(pid,12);elseif(pid=0)signal(12,func);while(k=1)sleep(1);printf(Bn);,非软中断方式main()intpid;pid=fork();if(pid0)printf(An);wait(0);elseif(pid=0)printf(Bn);,Linux无名管道通信,若只触发某些行为,软中断信号机制简捷有

5、效。若进程间需交换数据?-管道管道:用“管道”将读写进程连接在一起,写进程将数据从写入端写入,读进程将数据从读出端读出。数据量大小是系统定义的最大缓冲区字节数。,创建和使用无名管道的系统调用,1.创建管道格式:intpipe(intfp2);返回:0-正确返回,-1-错误返回参数:fp1为写入端,fp0为读出端功能:创建一个无名管道fp,fp1用于写,fp0用于读。2.读写管道-借助文件机制格式:写管道write(fp1,buf,size);读管道read(fp0,buf,size);参数:buf为数据缓冲区;size为l读写长度。头文件:,管道通信示例1,main()intp1,fd2;ch

6、aroutpipe50,inpipe50=“Thisisamessagefromchild.”;pipe(fd);p1=fork();if(p1=0)write(fd1,inpipe,50);/写信息到管道elseif(p10);wait(0);/等待子进程终止read(fd0,outpipe,50);/从管道读信息printf(%sn,outpipe);,父进程创建一个子进程和一个无名管道fd,子进程向管道写入“Thisisamessagefromchild!”后终止;父进程接收到子进程终止信号后从管道中读出并显示信息后结束。,管道通信示例2,main()intp1,fd2;charstr1

7、50,str250;pipe(fd);p1=fork();子进程执行的分支父进程执行的分支,父进程创建一个子进程和一个无名管道fd,子进程通过管道向父进程发送“Howareyou?”,父进程接收到消息后通过管道回送“Iamfine.”,父子进程将各自收到的消息显示出来。,elseif(p10)read(fd0,str1,50);printf(“Parentreceived:%sn”,str1);strcpy(str2,”Iamfine.”);write(fd1,str2,strlen(str2);,if(p1=0)strcpy(str1,”Howareyou?”);write(fd1,str1

8、,strlen(str1);read(fd0,str2,50);printf(“Childreceived:%sn”,str2);,管道通信示例2执行结果分析,父进程读不到数据被阻塞了,子进程把自己写入管道的数据读出来了!,修改管道通信示例2,若将子进程执行分析修改为:if(p1=0)strcpy(str1,”Howareyou?”);write(fd1,str1,strlen(str1);sleep(1);read(fd0,str2,50);printf(“Childreceived:%sn”,str2);,父进程不变:elseif(p10)read(fd0,str1,50);printf(

9、“Parentreceived:%sn”,str1);strcpy(str2,”Iamfine.”);write(fd1,str2,strlen(str2);,请分析上述代码执行结果:先调度到父进程?先调度到子进程?,无名管道通信机制特点,管道中的数据是字符流,工作于单向通信方式;管道逻辑上是由系统在内存中创建的临时文件实现的,物理上则由文件系统的高速缓冲区构成;无名管道只能供创建管道的进程及其子孙进程共享;管道为临界资源,各进程对管道的访问既有同步又有互斥,需要用户自己借助同步互斥机制以及文件机制来实现对管道的访问!,Linux消息缓冲队列,msg_queue链表-系统所有消息队列,一个ms

10、g_queue结构对应一个消息队列,msg结构,消息队列有一个称为关键字(key)的名字;收发消息前必须创建消息队列,使用消息队列描述符(msqid)来标识该消息队列。,Linux消息队列系统调用,19,intmsgget(key_tkey,intmsgflg);intmsgctl(intmsqid,intcmd,structmsqid_ds*buf);intmsgsnd(intmsqid,structmsgbuf*msgp,size_tmsgsz,intmsgflg);sszie_tmsgrcv(intmsqid,structmsgbuf*msgp,size_tmsgsz,longmsg_t

11、yp,intmsgflg);相关头文件:,,,1.创建或获取消息队列,格式:intmsgget(key_tkey,intmsgflag);功能:创建或获取标识为key的消息队列,并返回队列描述符。返回:正确返回该消息队列的描述符msgid;错误返回-1。参数:key消息队列标识符,为正整数。可由用户指定(适用于不同进程家族);也可使用IPC_PRIVATE由系统产生key值(适用于同一进程家族);msgflag标志或访问方式,由操作权限和控制命令进行或运算得到。操作权限:用户可读0400小组可读0040其他可读0004用户可写0200小组可写0020其他可写0002控制命令:IPC_CREAT

12、(值0001000),若队列不存在则创建。,21,/*有关头文件.*/main()intqid;key_tkey=113;qid=msgget(key,IPC_CREAT|0666);/创建消息队列if(qid0)perror(msgget);exit(1);printf(createdqueueid:%dn,qid);system(ipcs-q);/查看系统IPC的状态,创建消息队列示例,2.对消息队列的控制,格式:intmsgctl(intmsgid,intcmd,structmsqid_ds*buf);功能:查询、设置消息队列的状态;撤消消息队列。返回:函数调用成功返回0,不成功返回-1

13、。参数: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(qid0)perror(msgget);exit(1);printf(createdqueueid:%dn,qid);syst

14、em(“ipcs-q”);/查看系统IPC的状态if(msgctl(qid,IPC_RMID,NULL)0)perror(“msgctl”);exit(1);system(ipcs-q);printf(successfullyremoved%dqueuen,qid);,删除消息队列示例,3.发送消息,格式:intmsgsnd(intmsgid,structmsgbuf*msgp,intsize,intflag);功能:将msgp-msgbuf中的消息复制到msgid消息队列中,将之挂到队尾,唤醒等待消息的进程。参数:msgid执行msgget()返回的消息队列的描述符;msgp待发送的消息;s

15、ize由msgp指向的数据结构中消息长度;flag规定当消息队列满时应执行的动作,例如:若在flag中设置了IPC_NOWAIT,则当消息队列中的字节数超过最大值时,msgsnd立即返回,否则msgsnd睡眠。flag可置0。,25,/*有关头文件.*/structmsglongmtype;/消息类型charmtext511;/消息正文;intmain(void)intqid,pid;structmsgpmsg;/创建消息队列qid=msgget(113,IPC_CREAT|0666)if(qid0)perror(msgget);exit(1);system(“ipcs-q”);,发送消息示例

16、,/发送消息到队列上pmsg.mtype=getpid();sprintf(pmsg.mtext,hello!thisis%dn0,getpid();if(msgsnd(qid,4.接收消息,格式:intmsgrcv(intmsgid,structmsgbuf*msgp,intsize,inttype,intflag);功能:从msgid消息队列中接收一个消息:将消息复制到msgp-msgbuf中,并从队列中删除此消息,若消息未到则调用进程阻塞插入等待消息队列尾。参数:msgid消息队列描述符;msgp存放接收消息的用户缓冲区的首地址;size要接收字节数(一般为msgp中数据数组的大小);t

17、ype接收消息类型:0-接收队列的第一个消息;0-接收类型为type的第一个消息;0接收第一个类型小于或等于|type|的消息。flag若该队列无消息,内核应当做什么,可置0。,IPC_NOWAIT,立即返回IPC_EXCEPT与msgtype0配合使用,返回队列中第一个类型不为msgtype的消息IPC_NOERROR如果消息内容大于所请求的字节,则丢弃多余字节。,#includestructmsglongmtype;charmtext256;pmsg;main()intmsgqid,pid;msgqid=msgget(75,0777);printf(“msgid:%dn”,msgqid);

18、pmsg.mtype=1;*(int*)pmsg.text)=getpid();msgsnd(msgqid,27,消息通信示例模拟服务器与客户端,进程A发送如下消息给进程B:,进程B等待接收A的消息并回送如下消息:,#includeintmsgqid,pid;structmsglongmtype;charmtext256;pmsg;cancelqueue()msgctl(msgqid,IPC_RMID,0);exit(0);main()signal(2,cancelqueue);msgqid=msgget(75,0777|IPC_CREAT);while(1)msgrcv(msgqid,没有I

19、PC_CREAT,只获取不创建,28,消息通信示例模拟服务器与客户端运行结果,29,Linux共享存储区通信,消息缓冲需要CPU复制消息,进程间直接进行数据交换的通信方式?共享内存,与消息缓冲通信类似,Linux对共享内存通信也提供了4个系统调用函数:shmget()shmat()shmdt()shmctl()头文件:sys/types.h,linux/shm.h,共享存储区系统调用,1.创建或获取一个共享内存,格式:intshmid=shmget(key_tkey,intsize,intflag);功能:获得一个内部标识为shmid的共享存储区参数:key共享存储区关键字,由用户指定或由系统

20、产生(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存

21、储区的操作权限以及系统是否要舍除用户规定的地址。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()所返回的虚地址返回:正确返

22、回0错误返回-1,4.对共享内存的控制或查询,格式: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,I

23、PC_RMID,0);,共享内存通信实现方法:发送进程,1用shmget()创建或者获取指定key值的共享内存;2用shmat()将该共享内存附接到自己的虚拟地址空间;3.将需要发送的信息写入共享内存:共享内存定义为字符串,则可通过strcat(viraddr,buf)将buf追加到共享存储区尾部。或通过strcpy(viraddr,buf)将buf复制到共享内存中。共享内存定义为单变量,则可将*viraddr作为数值型变量对其进行操作。如*viradd=0。共享内存定义为数组变量,则可将viraddri作为下标变量使用。如viraddi=0。4.使用shmdt()断开共享内存。5如果不再使用

24、共享内存时,用shmctl()将其撤消,格式为:shmctl(shmid,IPC_RMID,0);,共享内存通信实现方法:接收进程,1.用shmget()创建或者获取指定key值的共享内存;2.用shmat()将该共享内存附接到自己的程序空间;3读取共享内存中的信息;4用shmdt()断开共享内存。5如果不再使用共享内存时,用shmctl()将其撤消,格式为:shmctl(shmid,IPC_RMID,0);,共享内存通信示例,#include#includemain()intshmid;char*va,bufBUFSIZ;shmid=shmget(22,BUFSIZ,0666|IPC_CRE

25、AT);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:%sn,va);shmdt(va)

26、;,发送程序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

27、指定信号量集中信号量数目,最大值在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.创建或获取信号量集,格式:intsemop(intsemid,structsembuf*sops,unsignednsops);返回:正确

温馨提示

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

评论

0/150

提交评论