106 SYSV进程间通信_第1页
106 SYSV进程间通信_第2页
106 SYSV进程间通信_第3页
106 SYSV进程间通信_第4页
106 SYSV进程间通信_第5页
已阅读5页,还剩21页未读 继续免费阅读

下载本文档

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

文档简介

1、10.610.6 SYS V SYS V 进程间通信进程间通信内容内容: : 信号量信号量; ; 消息队列消息队列; ; 共享内存。共享内存。10.6.1 10.6.1 三者三者共有的特性共有的特性IPCIPC资源资源:表示单独的消息队列、共享内存表示单独的消息队列、共享内存或是信号量集合。或是信号量集合。 三者均有三者均有XXXgetXXXget()及()及XXXctlXXXctl()()函数函数(XXXXXX代表代表msgmsg,semsem,shmshm三者之一)。三者之一)。 1) 1) XXXgetXXXget()()函数函数 两个共同参数:两个共同参数:keykey和和oflago

2、flag。 keykey既可由既可由ftokftok()()函数产生,也可以函数产生,也可以是是IPC_PRIVATEIPC_PRIVATE常量,常量,keykey值是值是IPCIPC资源的外资源的外部表示部表示。 oflagoflag包括读写权限,还可以包含包括读写权限,还可以包含IPC_IPC_CREATECREATE和和IPC_EXCLIPC_EXCL标志位。它们组合的效果标志位。它们组合的效果如下:如下: (1)(1)指定指定keykey为为IPC_PRIVATE,IPC_PRIVATE,保证创建一保证创建一个惟一的个惟一的IPCIPC资源。资源。 (2)(2)设置设置oflagofl

3、ag参数的参数的IPC_CREATEIPC_CREATE标志位,标志位,但不设置但不设置IPC_EXCLIPC_EXCL。如果相应如果相应keykey的的IPCIPC资源资源不存在,则创建一个不存在,则创建一个IPCIPC资源,否则返回已资源,否则返回已存在的存在的IPCIPC资源。资源。 (3)oflag(3)oflag参数的参数的IPC_CREATEIPC_CREATE和和IPC_EXCLIPC_EXCL同时设置。如果相应同时设置。如果相应keykey的的IPCIPC资源不存在,资源不存在,则创建一个则创建一个IPCIPC资源。否则返回一个错误信资源。否则返回一个错误信息。息。 2)XXX

4、ctl2)XXXctl()() 均提供均提供IPC_SETIPC_SET, ,IPC_STATIPC_STAT和和IPC_RMIDIPC_RMID命命令。前两者用来设置或得到令。前两者用来设置或得到IPCIPC资源的状态资源的状态信息,信息,IPC_RMIDIPC_RMID用来释放用来释放IPCIPC资源。资源。 共同的操作模式共同的操作模式: 都是先通过都是先通过XXXgetXXXget()()创建一个创建一个IPCIPC资源,资源,返回值是该返回值是该IPCIPC资源资源IDID。在以后的操作中,在以后的操作中,均以均以IPCIPC资源资源IDID为参数为参数, ,以对相应的以对相应的IP

5、CIPC资源资源进行操作。进行操作。 别的进程可以通过别的进程可以通过XXXgetXXXget()()取得已有的取得已有的IPCIPC资源资源IDID(权限允许的话)并对其操作,权限允许的话)并对其操作,从而使进程间通信成为可能。从而使进程间通信成为可能。共同的数据结构: 每一类每一类IPCIPC资源都有一个资源都有一个ipc_idsipc_ids结构的全局变结构的全局变量用来描述同一类资源的公有数据,三个全局变量量用来描述同一类资源的公有数据,三个全局变量分别是分别是semid_dssemid_ds,msgid_dsmsgid_ds和和shmid_dsshmid_ds。structstruc

6、t ipc_idsipc_ids intint size; / size; /* * entries entries数组的大小数组的大小* */ / intint in_use; / in_use; /* * entries entries数组已使用的元素个数数组已使用的元素个数* */ / intint max_id; max_id; unsigned short unsigned short seqseq; ; unsigned short unsigned short seq_maxseq_max; ; tructtruct semaphore semaphore semsem; /;

7、/* *控制对控制对ipc_idsipc_ids结构的访问结构的访问* */ / spinlock_tspinlock_t aryary;/;/* *自旋锁控制对数组自旋锁控制对数组entriesentries的访问的访问* */ / structstruct ipc_idipc_id* * entries; entries;structstruct ipc_idipc_id structstruct kern_ipc_permkern_ipc_perm* * p; p; 数组数组entriesentries的每一项指向一个的每一项指向一个kern_ipc_permkern_ipc_perm结

8、构,结构,kern_ipc_permkern_ipc_perm结构表示每一个结构表示每一个IPCIPC资源的资源的属性,用来控制操作权限属性,用来控制操作权限。structstruct kern_ipc_permkern_ipc_perm key_t key;/ key_t key;/* *用户提供的键值用户提供的键值, ,为为XXXgetXXXget()()所用所用* */ / uid_tuid_t uiduid; /; /* *创建者用户创建者用户IDID* */ / gid_tgid_t gidgid; /; /* *创建者组创建者组IDID* */ / uid_tuid_t cuidc

9、uid; /; /* *所有者用户所有者用户IDID* */ / gid_tgid_t cgidcgid; /; /* *所有者组所有者组IDID* */ / mode_t mode; / mode_t mode; /* *操作权限,包括读、写等操作权限,包括读、写等* */ / unsigned long unsigned long seqseq; ; ; ; 因为每个因为每个IPCIPC资源描述符的第一个成员就是资源描述符的第一个成员就是kern_ipc_permkern_ipc_perm结构。因此,我们可以认为数组结构。因此,我们可以认为数组entries entries 的每一非空项均

10、指向一个的每一非空项均指向一个IPCIPC资源。资源。IPCIPC资源资源IDID与与entriesentries数组下标的联系:数组下标的联系: 1)1)当创建一个当创建一个IPCIPC资源时资源时 2)2)当知道当知道IPCIPC资源资源IDID时,可通过时,可通过IPCIPC资源资源ID ID SEQ_MULTIPLIERSEQ_MULTIPLIER得到其在得到其在entriesentries数数组中的组中的indexindex,从而找到相应的从而找到相应的IPCIPC资源。资源。 3)why3)why保证在一段时期内保证在一段时期内IPCIPC资源资源IDID的惟的惟一性。一性。 调用

11、函数调用函数ipc_addidipc_addid( )( )从相应从相应ipc_idsipc_ids结构的结构的entriesentries数组中找出第一个未使用的项,然后返回其数组中找出第一个未使用的项,然后返回其下标下标indexindex。 返回返回IPCIPC资源资源IDIDIPCIPC资源资源ID=ID=SEQ_MULTIPLIERSEQ_MULTIPLIERseqseqindexindexSEQ_ MULTIPLIERSEQ_ MULTIPLIER是可用资源的最大数目,是可用资源的最大数目,seqseq是是ipc_idsipc_ids结构中的结构中的seqseq。每当分配一个每当分

12、配一个IPCIPC资源时,资源时,ipc_idsipc_ids结构中的结构中的seqseq就增就增1 1。10.6.210.6.2 信号量信号量 信号量是具有整数值的对象,它支持信号量是具有整数值的对象,它支持P P,V V原语。进程可以利用信号量实现同步和原语。进程可以利用信号量实现同步和互斥。互斥。 SYSVSYSV支持的信号量实质上是一个信号支持的信号量实质上是一个信号量集合量集合, ,由多个单独的信号量组成。我们由多个单独的信号量组成。我们称称SYSVSYSV信号量为信号量集合,而单个的信号量为信号量集合,而单个的信号量直接称为信号量。信号量直接称为信号量。 信号量集合在内核中用结构信

13、号量集合在内核中用结构sem_arraysem_array表示。表示。structstruct sem_arraysem_array structstruct kern_ipc_permkern_ipc_permsem_permsem_perm; ; time_t time_t sem_otimesem_otime; ;/ /* * 最近一次操作时间最近一次操作时间 * */ / time_t time_t sem_ctimesem_ctime; ;/ /* * 最近一次的改变时间最近一次的改变时间 * */ / structstruct semsem* *sem_basesem_base;

14、/; /* *指向第一个信号量指向第一个信号量 * */ / structstruct sem_queuesem_queue * *sem_pendingsem_pending;/;/* * 挂起操作队列挂起操作队列* */ / structstruct sem_queuesem_queue * * *sem_pending_lastsem_pending_last; ; structstruct sem_undosem_undo * *undo;undo; unsigned long unsigned long sem_nsemssem_nsems;/;/* *信号量的个数信号量的个数* *

15、/ /; 信号量集合中的每一个信号用结构信号量集合中的每一个信号用结构semsem表示:表示: structstruct semsem intintsemvalsemval;/;/* * 信号量的当前值信号量的当前值 * */ /intintsempidsempid;/;/* * 最近对信号量操作进程的最近对信号量操作进程的pidpid * */ / ; ; 信号量的初始值可以调用函数信号量的初始值可以调用函数semctlsemctl( )( )进行进行设置。设置。 用户可以调用函数用户可以调用函数semopsemop()()对信号量集合中的对信号量集合中的一个或多个信号量进行操作。一个或多个

16、信号量进行操作。 每一个操作都是每一个操作都是sembufsembuf结构变量:结构变量: structstruct sembufsembuf unsigned short unsigned short sem_numsem_num;/;/* *在在sem_basesem_base 数组中的下标数组中的下标* */ / short short sem_opsem_op; ; short short sem_flgsem_flg; ;intint semop(intsemop(int semidsemid, , structstruct sembufsembuf * *opsptropsptr,

17、 , size_t size_t nopsnops);); semidsemid : IPC : IPC资源资源IDID opsptropsptr: : 操作的集合操作的集合 nopsnops: : 数组数组opsptropsptr的大小的大小 内核必须保证操作数组内核必须保证操作数组opsptropsptr原子的执行原子的执行。sem_numbersem_number指明是对哪一个信号操作。指明是对哪一个信号操作。sem_flagsem_flag指明一些操作标志位,可以有如下值:指明一些操作标志位,可以有如下值: (1)SEM_UNDO(1)SEM_UNDO。当进程结束但还拥有信号量当进程结

18、束但还拥有信号量资源时,应将信号量资源返还给相应的信号量集资源时,应将信号量资源返还给相应的信号量集合。内核有一个合。内核有一个sem_undosem_undo结构用于跟踪这方面结构用于跟踪这方面的情况,进程描述符有个的情况,进程描述符有个semundosemundo成员记录进程成员记录进程这方面的信息。这方面的信息。 (2)(2)IPC_NOWAITIPC_NOWAIT。当操作不能立即完成时,当操作不能立即完成时,若若IPC_NOWAITIPC_NOWAIT被设置的话,进程立即返回。被设置的话,进程立即返回。 否则进程进入睡眠状态,等待时机成熟时被否则进程进入睡眠状态,等待时机成熟时被唤醒完

19、成该操作。唤醒完成该操作。 sem_opsem_op指定具体的操作,它的值有如下指定具体的操作,它的值有如下含义:含义: (1)(1)大于大于0 0,则将该值加到信号量的当前,则将该值加到信号量的当前值上。值上。 (2)(2)等于等于0 0,那么用户希望信号量的当前,那么用户希望信号量的当前值变为值变为0 0。如果值已经是。如果值已经是0 0,则立即返回。如,则立即返回。如果不是果不是0 0,则取决于,则取决于IPC_NOWAITIPC_NOWAIT是否被设置。是否被设置。 (3)(3)小于小于0 0,则要看信号量的当前值是否,则要看信号量的当前值是否大于等于大于等于sem_opsem_op的

20、绝对值。如果大于等于它的绝对值。如果大于等于它的绝对值的绝对值,就从信号量的当前值中减去就从信号量的当前值中减去sem_opsem_op的绝对值。如果小于它的绝对值,则的绝对值。如果小于它的绝对值,则取决于取决于IPC_NOWAITIPC_NOWAIT是否被设置是否被设置。 当进程的信号量操作不能完成睡眠时,需要将一当进程的信号量操作不能完成睡眠时,需要将一个代表着当前进程的个代表着当前进程的sem_queuesem_queue结构链入相应的信结构链入相应的信号量集合的等待队列,即号量集合的等待队列,即sem_arraysem_array结构的结构的sem_pendingsem_pending

21、队列。队列。structstruct sem_queuesem_queue structstruct sem_queuesem_queue * *next; /next; /* *队列中的下一个元素队列中的下一个元素* */ / structstruct sem_queuesem_queue * * *prevprev; /; /* *队列中的前一个元素队列中的前一个元素* */ / structstruct task_structtask_struct * *sleeper;/sleeper;/* * 睡眠进程的描述符睡眠进程的描述符* */ / structstruct sem_undos

22、em_undo * *undo;undo; intint pidpid; ; / /* * 睡眠进程的睡眠进程的pidpid * */ / intint status;status; structstruct sem_arraysem_array * *smasma; /; /* * 所属的信号量集合所属的信号量集合 * */ / structstruct sembufsembuf * *sops; /sops; /* * 挂起的操作数组挂起的操作数组 * */ / intint nsopsnsops; ; / /* * 挂起的操作个数挂起的操作个数* */ / . .;10.6.310.6.

23、3 消息队列消息队列 具有权限的进程可以往消息队列中读写消息,具有权限的进程可以往消息队列中读写消息,这就是消息队列支持进程通信的方式这就是消息队列支持进程通信的方式。 msgsndmsgsnd()()函数将消息放入队列中。函数将消息放入队列中。 intint msgsnd(intmsgsnd(int msqidmsqid, const void , const void * *msgpmsgp, , size_t size_t msgszmsgsz, , intint msgflgmsgflg); ); msqidmsqid: 消息队列的资源消息队列的资源IDID号。号。 msgpmsgp:

24、 消息缓冲区的首地址。消息缓冲区消息消息缓冲区的首地址。消息缓冲区消息的类型及数据两部分组成。的类型及数据两部分组成。 msgszmsgsz:消息缓冲区的长度。消息缓冲区的长度。 msgflgmsgflg:可以是可以是0 0,也可以是,也可以是IPC_NOWAITIPC_NOWAIT。 msgrcvmsgrcv( )( )从某个消息队列中读一个消息并将其移出从某个消息队列中读一个消息并将其移出消息队列。消息队列。intint msgrcv(intmsgrcv(int msqidmsqid, void , void * *msgpmsgp, , intint msgszmsgsz, long ,

25、 long msgtypmsgtyp, , intint msgflgmsgflg); ); msgpmsgp:接收消息的缓冲区首址。接收消息的缓冲区首址。 msgszmsgsz:接收缓冲区的大小,这是函数能返回的最大接收缓冲区的大小,这是函数能返回的最大数据量。数据量。 msgtypmsgtyp:指定接收消息的类型。分为三种情况指定接收消息的类型。分为三种情况: : 值为值为0 0,返回队列中的第一个消息。,返回队列中的第一个消息。 值大于值大于0 0,返回类型为,返回类型为msgtypemsgtype的第一个消息。的第一个消息。 值小于值小于0 0,则返回类型值小于或等于,则返回类型值小于

26、或等于msgtypemsgtype 的绝对值的消息中类型值最小的第一个消息。的绝对值的消息中类型值最小的第一个消息。 m s g f l gm s g f l g : 可 以 是可 以 是 I P C _ N O W A I TI P C _ N O W A I T , 还 可 指 定 为还 可 指 定 为MSG_NOERRORMSG_NOERROR。MSG_NOERRORMSG_NOERROR允许消息长度大于接收缓冲允许消息长度大于接收缓冲区长度时截短消息返回。区长度时截短消息返回。在内核中消息队列用在内核中消息队列用msg_queuemsg_queue结构表示。结构表示。structstr

27、uct msg_queuemsg_queue structstruct kern_ipc_permkern_ipc_perm q_perm; q_perm; time_t time_t q_stimeq_stime; ;/ /* *最近一次最近一次msgsndmsgsnd时间时间* */ / time_t time_t q_rtimeq_rtime; ;/ /* *最近一次最近一次msgrcvmsgrcv 时间时间* */ / time_t time_t q_ctimeq_ctime; /; /* * 最近的改变时间最近的改变时间 * */ / unsigned long unsigned l

28、ong q_cbytesq_cbytes; /; /* * 队列中的字节数队列中的字节数 * */ / unsigned long unsigned long q_qnumq_qnum; ;/ /* * 队列中的消息数目队列中的消息数目 * */ /unsigned long unsigned long q_qbytesq_qbytes;/;/* *队列中允许的最大字节数队列中允许的最大字节数 * */ / pid_tpid_t q_lspidq_lspid;/;/* *最近一次最近一次msgsndmsgsnd( )( )发送进程的发送进程的pidpid * */ / pid_tpid_t q

29、_lrpidq_lrpid;/;/* *最近一次最近一次msgrcvmsgrcv( )( )接收进程的接收进程的pidpid * */ / structstruct list_head q_messages; / list_head q_messages; /* *消息队列消息队列* */ / structstruct list_head q_receivers; / list_head q_receivers; /* *待接收消息的睡待接收消息的睡 眠进程队列眠进程队列* */ / structstruct list_head q_senders; / list_head q_senders

30、; /* *待发送消息的睡眠待发送消息的睡眠 进程队列进程队列* */ /; 若若IPC_NOWAITIPC_NOWAIT未被设置,则当消息队列的容量未被设置,则当消息队列的容量已满时,发送消息的进程会进入睡眠状态并添加已满时,发送消息的进程会进入睡眠状态并添加到相应的到相应的q_sendersq_senders队列,而当消息队列中无合队列,而当消息队列中无合适的消息时,接收进程会进入睡眠状态并添加到适的消息时,接收进程会进入睡眠状态并添加到相应的相应的q_receiversq_receivers队列。队列。 消息队列中的每个消息都链入消息队列中的每个消息都链入q_messageq_messa

31、ge队列队列中,每个消息用一个中,每个消息用一个msg_msgmsg_msg结构描述。结构描述。structstruct msg_msgmsg_msg structstruct list_head m_list; / list_head m_list; /* *消息队列链表消息队列链表* */ / long m_type; / long m_type; /* * 消息的类型消息的类型 * */ / intint m_tsm_ts; /; /* * 消息的长度消息的长度 * */ / structstruct msg_msgsegmsg_msgseg* * next; / next; /* *

32、链接属于这个链接属于这个消息的下一个消息片消息的下一个消息片* */ /;structstruct msg_msgsegmsg_msgseg structstruct msg_msgsegmsg_msgseg* * next; next; msg_msgmsg_msg结构只是一个消息头部,并不包含结构只是一个消息头部,并不包含消息的数据部分。数据部分的空间紧接消息的数据部分。数据部分的空间紧接msg_msgmsg_msg结构分配结构分配,但是当数据部分的空间与但是当数据部分的空间与msg_msgmsg_msg结结构所占空间大于一个页面时,则将其以页面为单构所占空间大于一个页面时,则将其以页面为

33、单位分片。第一个页面存储位分片。第一个页面存储msg_msgmsg_msg结构与首部分结构与首部分数 据 , 随 后 的 再 分 配 空 间 则 存 储数 据 , 随 后 的 再 分 配 空 间 则 存 储 s t r u c ts t r u c t msg_msgsegmsg_msgseg结构与剩余的数据,如果这两者所结构与剩余的数据,如果这两者所占空间之和仍大于一个页面,则继续分配下去。占空间之和仍大于一个页面,则继续分配下去。msg_msgsegmsg_msgseg结构用以把消息片链接在一起。结构用以把消息片链接在一起。 10.6.4 10.6.4 共享内存共享内存 共享内存是多个进程

34、共享的一块内存区域。共享内存是多个进程共享的一块内存区域。不同的进程可把共享内存映射到自己的一块地不同的进程可把共享内存映射到自己的一块地址空间址空间, ,不同的进程进行映射的地址空间不一定不同的进程进行映射的地址空间不一定相同。相同。 共享内存区的进程对该区域的操作是互见的。共享内存区的进程对该区域的操作是互见的。 共享内存没有提供进程同步与互斥的机制,共享内存没有提供进程同步与互斥的机制, 往往需要和信号量配合使用。往往需要和信号量配合使用。 相比起其他进程通信方式,共享内存在进行相比起其他进程通信方式,共享内存在进行数据交换方面是效率比较高的。无需用户态、数据交换方面是效率比较高的。无需

35、用户态、核心态切换开销。核心态切换开销。 shmgetshmget()()函数有一个参数指定共享内存区域的函数有一个参数指定共享内存区域的大小,该函数建立的共享内存区在内核中用大小,该函数建立的共享内存区在内核中用shmid_kernelshmid_kernel结构表示。结构表示。structstruct shmid_kernelshmid_kernel structstruct kern_ipc_permkern_ipc_permshm_permshm_perm; ; structstruct file file * *shm_fileshm_file; ; intint id; id; u

36、nsigned long unsigned long shm_nattchshm_nattch;/;/* *已建立映射的数目已建立映射的数目* */ / unsigned long unsigned long shm_segszshm_segsz;/;/* *共享内存区的大小共享内存区的大小* */ / time_t time_tshm_atimshm_atim; ; time_t time_tshm_dtimshm_dtim; ; time_t time_tshm_ctimshm_ctim; ; pid_tpid_tshm_cpridshm_cprid; ; pid_tpid_tshm_lpridshm_lprid; ; shmgetshmget()()创建的共享内存区域并没有立即分创建的共享内存区域并没有立即分配物理内存,而是创建一个文件对象配物理内存,而是创建一个文件对象shm_fileshm_file来来描述该区域,而该文件属于描述该区域,而该文件属于shmshm文件系统。文件系统。shmshm文文件系统是一个内存文件系统,它不依赖于磁盘文件系统是一个内存文件系统,它不依赖

温馨提示

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

评论

0/150

提交评论