




版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
1、2021-7-17linux进程间通信1第第4章章 进程间通信进程间通信 32021-7-17linux进程间通信24.7 Linux信号量信号量4.7.1 Linux的信号量的信号量 作为作为IPC机制的一种,与上述其它通信方式类似,机制的一种,与上述其它通信方式类似,也要通过也要通过kern_ipc_perm结构中的结构中的key来唯一标识一来唯一标识一个信号量集,并通过该结构设置并检查访问权限。个信号量集,并通过该结构设置并检查访问权限。 针对信号量集,系统中维护了一个由信号量集组成针对信号量集,系统中维护了一个由信号量集组成的数组,数组中的每个单元指向一个信号量集。每一的数组,数组中的
2、每个单元指向一个信号量集。每一个信号量集由一个个信号量集由一个sem_array结构来描述,该结构定结构来描述,该结构定义在文件义在文件/usr/src/linux-2.4/include/linux/sem.h中。中。2021-7-17linux进程间通信34.7.1 Linux的信号量的信号量2021-7-17linux进程间通信44.7.2 有关信号量的系统调用函数有关信号量的系统调用函数Linux提供下列提供下列3个有关信号量的系统调用函数:个有关信号量的系统调用函数:semget()semop()semctl()下面分别予以介绍。下面分别予以介绍。2021-7-17linux进程间通
3、信54.7.2 有关信号量的系统调用函数有关信号量的系统调用函数1.创建一个新的信号量集或获取一个已经存在的信号量集创建一个新的信号量集或获取一个已经存在的信号量集命令格式:命令格式:int semget(key_t key, int nsems, int semflg);返回值:返回值:正确返回:信号量集的标识符正确返回:信号量集的标识符错误返回:错误返回:-12021-7-17linux进程间通信61.创建一个新的信号量集或获取一个已经存在的信号量集创建一个新的信号量集或获取一个已经存在的信号量集参数说明:参数说明:key信号量集的信号量集的key值:值:使用使用IPC_PRIVATE,由
4、系统产生,由系统产生key值并返回标识符,或者返回值并返回标识符,或者返回key值已存在的值已存在的信号量集的标识符。信号量集的标识符。 key值不为值不为IPC_PRIVATE而是由用户指定一个非而是由用户指定一个非0整型数值,则对信号量集的打整型数值,则对信号量集的打开或存取操作依赖于开或存取操作依赖于semflag参数的取值。参数的取值。nsems指定打开或者新创建的信号量集将包含的信号量的数目;如果该指定打开或者新创建的信号量集将包含的信号量的数目;如果该key值的值的信号量集已存在,而信号量集已存在,而semflg只指定了只指定了IPC_CREAT标志,那么参数标志,那么参数nsem
5、s必须与必须与原来的值一致,否则也会返回错误信息。该参数最大值在原来的值一致,否则也会返回错误信息。该参数最大值在linux/sem.h中被定义:中被定义:#define SEMMSL 250 /* = 8 000 */semflg当当key值不为值不为IPC_PRIVATE:若只设置若只设置semflag的的IPC_CREAT位,则创建一个信号量集,如果该信号量集已位,则创建一个信号量集,如果该信号量集已经存在,则返回其标识符经存在,则返回其标识符若设置若设置semflag的的IPC_CREAT|IPC_EXCL位,则创建一个新的信号量集,如果位,则创建一个新的信号量集,如果该该key值的信
6、号量集已经存在则返回错误信息值的信号量集已经存在则返回错误信息只设置只设置IPC_EXCL位而不设置位而不设置IPC_CREAT位没有任何意义。位没有任何意义。2021-7-17linux进程间通信71.创建一个新的信号量集或获取一个已经存在的信号量集创建一个新的信号量集或获取一个已经存在的信号量集实验中,使用该调用创建一个只含一个信号量的信号量集,格式为:semid=semget(IPC_PRIVATE,1, IPC_CREAT|0666);其中的IPC_PRIVATE可以使用具体的整型数值取代。2021-7-17linux进程间通信82.对信号量的对信号量的P、V操作操作命令格式:命令格式
7、:int semop(int semid, struct sembuf * sops, unsigned nsops);返回值:返回值:正确返回:正确返回:0错误返回:错误返回:-1参数说明:参数说明:semid信号量集的标识符,由信号量集的标识符,由semget()得到。()得到。sops指向一个指向一个sembuf结构数组,该数组的每个元素对应一次信结构数组,该数组的每个元素对应一次信号量操作。号量操作。2021-7-17linux进程间通信92.对信号量的对信号量的P、V操作操作其其sembuf数据结构如下:数据结构如下:struct sembuf unsigned short sem_
8、num; /* semaphore index in array */shortsem_op;/* semaphore operation */shortsem_flg;/* operation flags */;其其中的参数含义如下所示:中的参数含义如下所示:2021-7-17linux进程间通信102.对信号量的对信号量的P、V操作操作信号量的信号量的sem_num值标明它是信号量集的第几个元素,第一个信号量为值标明它是信号量集的第几个元素,第一个信号量为0,第二个,第二个为为1,依次类推。,依次类推。semop确定对确定对sem_num指定的信号量采取何种操作,它可以为负数、正数和零。指
9、定的信号量采取何种操作,它可以为负数、正数和零。如果如果sem_op为负数:则相当于为负数:则相当于P操作,从信号量的值中减去操作,从信号量的值中减去sem_op的绝对值:的绝对值: 其差如果大于其差如果大于0,则表示该进程可以使用临界资源进入临界区;,则表示该进程可以使用临界资源进入临界区; 其差如果小于其差如果小于0,在没有指定,在没有指定IPC_NOWAIT的情况下,该进程睡眠,并插入的情况下,该进程睡眠,并插入sem_queues等待队列尾部,直到请求的条件得到满足;如果指定了等待队列尾部,直到请求的条件得到满足;如果指定了IPC_NOWAIT,则出错返回。则出错返回。如果如果sem_
10、op为正数:此时相当于为正数:此时相当于V操作,把它的值加到信号量中,这也意味着该操作,把它的值加到信号量中,这也意味着该进程释放资源。如果是互斥则出临界区,释放临界资源。进程释放资源。如果是互斥则出临界区,释放临界资源。如果如果sem_op为为0:则该进程将睡眠直到信号量的值也为:则该进程将睡眠直到信号量的值也为0。系统会按顺序检查信号量等待队列系统会按顺序检查信号量等待队列(sem_pending)中的每一个成员,查看在当前信号量中的每一个成员,查看在当前信号量的状态下,其请求的操作是否可以成功,如果可以,则将它从等待队列中唤醒,并的状态下,其请求的操作是否可以成功,如果可以,则将它从等待
11、队列中唤醒,并插入到就绪队列中等待调度运行。插入到就绪队列中等待调度运行。sem_flg指明操作的执行模式,它有两个标志位:指明操作的执行模式,它有两个标志位: IPC_NOWAIT:指明以非阻塞方:指明以非阻塞方式操作信号量。式操作信号量。 SEM_UNDO: 指明内核为信号量操作保留恢复值指明内核为信号量操作保留恢复值nsops是第二个参数所指向的是第二个参数所指向的sembuf结构数组中元素的个数,如果只有一个信号结构数组中元素的个数,如果只有一个信号量量nsops值值为为1。 2021-7-17linux进程间通信112.对信号量的对信号量的P、V操作操作在实验中,使用该系统调用实现在
12、实验中,使用该系统调用实现P、V操作,使用格式为:操作,使用格式为:struct sembuf P,V;semop(semid, &P, 1); /对信号量对信号量semid执行执行P操作操作semop(semid, &V, 1); /对信号量对信号量semid执行执行V操作操作2021-7-17linux进程间通信123信号量集的控制函数信号量集的控制函数命令格式:命令格式:int semctl(int semid, int semnum, int cmd, union semun arg);返回值:返回值: 操作成功返回:根据操作成功返回:根据cmd的不同返回需要的值或的不同返回需要的值或
13、0 错误返回:错误返回:-12021-7-17linux进程间通信133信号量集的控制函数信号量集的控制函数参数说明:参数说明:semid信号量集的标识符,由信号量集的标识符,由semget()得到;()得到;semnum指定指定semid信号量集的第几个信号量,在信号量集的第几个信号量,在撤消信号量集时,此参数可以缺省;撤消信号量集时,此参数可以缺省;cmd用于指定操作类别:用于指定操作类别: SETVAL:置信号量:置信号量semval域值为域值为arg.val。 IPC_RMID:删除指定信号量集。能够进行此项操作:删除指定信号量集。能够进行此项操作的 进 程 限 于 超 级 用 户 、
14、的 进 程 限 于 超 级 用 户 、 s e m _ p e r m . c u i d 或或sem_perm.uid。2021-7-17linux进程间通信143信号量集的控制函数信号量集的控制函数实验中使用该系统调用实现以下功能:实验中使用该系统调用实现以下功能:为信号量赋初值,格式为:为信号量赋初值,格式为:union semun arg;arg.val=初值初值; semctl(semid,0,SETVAL,arg);其中其中0表示第表示第0个信号量,个信号量,arg的值由的值由arg.val决定,所以必须事先为决定,所以必须事先为arg.val赋值。赋值。撤消信号量集,格式为:撤消
15、信号量集,格式为:semctl(semid,IPC_RMID,0);上述系统调用使用下列上述系统调用使用下列头函数:头函数:#include#include2021-7-17linux进程间通信154.7.3 信号量及其信号量及其P、V操作的实现操作的实现信号量及其信号量及其P、V操作的实现方式归纳如下:操作的实现方式归纳如下:1 定义信号量标识符:定义信号量标识符:int semid;如果有如果有n个信号量,则需要分别定义个信号量,则需要分别定义n个不同的信号量标识符。个不同的信号量标识符。2 定义信号量数据结构定义信号量数据结构定义定义P、V操作所用的数据结构:操作所用的数据结构:stru
16、ct sembuf P,V; 定义给信号量赋初值的参数数据结构:定义给信号量赋初值的参数数据结构:union semun arg;3 申请只有一个信号量的信号量集申请只有一个信号量的信号量集semid=semget(IPC_PRIVITE,1,IPC_0666);其中,第一个参数:其中,第一个参数:IPC_PRIVATE由系统产生由系统产生key值,也可以由用户使用具值,也可以由用户使用具体的整型数值作为体的整型数值作为key值指定;第二个参数表示信号量集中只有一个信值指定;第二个参数表示信号量集中只有一个信号量;操作权限取决于最后一个参数,号量;操作权限取决于最后一个参数,0666表示任意用
17、户可读可写,只表示任意用户可读可写,只设置设置semflag的的IPC_CREAT位,则创建一个信号量集,如果该信号量集位,则创建一个信号量集,如果该信号量集已经存在,则返回其标识符。已经存在,则返回其标识符。4 分别对每个信号量分别对每个信号量semid赋初值赋初值arg.val=初值初值;semctl(semid,0,SETVAL,arg);2021-7-17linux进程间通信164.7.3 信号量及其信号量及其P、V操作的实现操作的实现5. 定义信号量的定义信号量的P操作(供所有信号量的操作(供所有信号量的P操作使用)操作使用)P.sem_num=0;P.sem_op=-1;/*-1表
18、示表示P操作时对信号量减操作时对信号量减1*/P.sem_flg=SEM_UNDO;6. 定义信号量的定义信号量的V操作(供所有信号量的操作(供所有信号量的V操作使用)操作使用)V.sem_num=0;V.sem_op=1;/*1表示表示V操作时对信号量加操作时对信号量加1*/V.sem_flg=SEM_UNDO;7. 对信号量对信号量semid执行执行P操作:操作:semop(semid,&P,1);8. 对信号量对信号量semid执行执行V操作:操作:semop(semid,&V,1);9. 撤消信号量:撤消信号量:semctl(semid,IPC_RMID,0);因为信号量不是普通变量,
19、对它赋初值只能通过系统调用函数因为信号量不是普通变量,对它赋初值只能通过系统调用函数semctl(semid,0,SETVAL,arg)进行,进行,其值的修改只能通过其值的修改只能通过P、V操作,而操作,而不能使用普通的赋值语句。不能使用普通的赋值语句。因此其初值和信号量的因此其初值和信号量的P、V操作需要事先定义好以后,然后才能在进程中执行操作需要事先定义好以后,然后才能在进程中执行P、V操作。操作。2021-7-17linux进程间通信174.7.4 应用举例应用举例1.利用信号量实现进程互斥利用信号量实现进程互斥例例4-9 设有父子设有父子2个进程共享一个临界资源,每个进程循环进入该个进
20、程共享一个临界资源,每个进程循环进入该临界区临界区3次:父进程每次进入临界区后显示次:父进程每次进入临界区后显示“prnt in”,出临界区,出临界区则显示则显示“prnt out”;子进程每次进入临界区后显示;子进程每次进入临界区后显示“chld in”出出临界区则显示临界区则显示“chld out”。观察运行结果,应该是一个进程出来。观察运行结果,应该是一个进程出来后另一个才能进去。后另一个才能进去。分析:分析:对临界区设置互斥信号量对临界区设置互斥信号量mutex,其内部标识为,其内部标识为mutexid,初值为,初值为1。程序中使用睡眠延时程序中使用睡眠延时1秒来模拟进入临界区前和进入
21、后所执行的程序。秒来模拟进入临界区前和进入后所执行的程序。2021-7-17linux进程间通信18程序清单:文件名程序清单:文件名sem.c#include#include#include#include#includeint mutexid;/定义信号量标识定义信号量标识int main()int chld,i,j;/*定义数据结构定义数据结构*/struct sembuf P,V;union semun arg;/*创建只含有一个互斥信号量元素的信号量集创建只含有一个互斥信号量元素的信号量集*/mutexid=semget(IPC_PRIVATE,1,0666|IPC_CREAT);/*
22、为信号量赋初值为信号量赋初值*/arg.val=1;if(semctl(mutexid,0,SETVAL,arg)=-1)perror(semctl setval error);2021-7-17linux进程间通信19 /*定义定义P、V操作操作*/P.sem_num=0;P.sem_op=-1;P.sem_flg=SEM_UNDO;V.sem_num=0;V.sem_op=1;V.sem_flg=SEM_UNDO;while(chld=fork()=-1); /创建子进程创建子进程if(chld0) /父进程返回父进程返回i=1;while(i=3)/循环循环3次次sleep(1);sem
23、op(mutexid,&P,1); /进入临界区前执行进入临界区前执行P操作操作printf(prnt inn);sleep(1);printf(prnt outn);semop(mutexid,&V,1); /出临界区执行出临界区执行V操作操作i+;wait(0);/等待子进程终止等待子进程终止semctl(mutexid,IPC_RMID,0);/撤消信号量撤消信号量exit(0);2021-7-17linux进程间通信20else/子进程返回子进程返回j=1;while(j=3)/循环循环3次次sleep(1);semop(mutexid,&P,1); /进入临界区前执行进入临界区前执行
24、P操作操作printf(chld inn);sleep(1);printf(chld outn);semop(mutexid,&V,1); /出临界区执行出临界区执行V操作操作j+;exit(0);/子进程终止子进程终止2021-7-17linux进程间通信21编译连接及运行结果:编译连接及运行结果:2021-7-17linux进程间通信222.利用信号量实现进程同步利用信号量实现进程同步例例4-10 父进程创建一个子进程,父子进程共享一个存储区,子进程向共享父进程创建一个子进程,父子进程共享一个存储区,子进程向共享存储区中以覆盖方式写信息,父进程从该共享存储区中读信息并显示信存储区中以覆盖方
25、式写信息,父进程从该共享存储区中读信息并显示信息。父子进程轮流读写,即子进程写一个信息到共享内存中,父进程从息。父子进程轮流读写,即子进程写一个信息到共享内存中,父进程从中读该信息输出;然后子进程再写第中读该信息输出;然后子进程再写第2个信息,父进程再读出第个信息,父进程再读出第2个信息个信息输出,如图输出,如图4 6所示。当信息为所示。当信息为“end”时读写进程结束。时读写进程结束。父进程父进程子进程子进程单缓冲区单缓冲区图图4 6 单缓冲区同步问题单缓冲区同步问题2021-7-17linux进程间通信232.利用信号量实现进程同步利用信号量实现进程同步同步分析:同步分析:这是一个单缓冲区
26、同步问题,在第这是一个单缓冲区同步问题,在第3章中已经讨论过这类问题的同步章中已经讨论过这类问题的同步算法,读写缓冲区的两个进程之间只需要同步不需要互斥,请参算法,读写缓冲区的两个进程之间只需要同步不需要互斥,请参阅阅3.3.6节中的节中的单缓冲区同步问题单缓冲区同步问题。同步算法:同步算法:子进程执行条件为单缓冲区有空,设信号量子进程执行条件为单缓冲区有空,设信号量empty,初值为,初值为1;父进程执行条件为单缓冲区有数,设信号量父进程执行条件为单缓冲区有数,设信号量full,初值为,初值为0;上述信号量可以由父进程定义、申请、初始化,然后由父子进程共上述信号量可以由父进程定义、申请、初始
27、化,然后由父子进程共享使用,子进程结束后由父进程撤消。享使用,子进程结束后由父进程撤消。共享内存设计:共享内存设计:父子进程共享一个内存区,可以由父进程申请、附接,然后由父子父子进程共享一个内存区,可以由父进程申请、附接,然后由父子进程共享使用,子进程结束后由父进程撤消。进程共享使用,子进程结束后由父进程撤消。2021-7-17linux进程间通信24程序清单,文件名为程序清单,文件名为sem2.c:#include#include#include#include#include#include#include/*定义信号量内部标识定义信号量内部标识*/int emptyid;int full
28、id;main()int chld,i,j;/*定义信号量数据结构定义信号量数据结构*/struct sembuf P,V;union semun arg;/*定义共享内存定义共享内存*/int shmid;char *viraddr;char bufferBUFSIZ;2021-7-17linux进程间通信25 /*创建信号量并初始化创建信号量并初始化*/emptyid=semget(IPC_PRIVATE,1,IPC_CREAT|0666);fullid=semget(IPC_PRIVATE,1,IPC_CREAT|0666);arg.val=1;if(semctl(emptyid,0,S
29、ETVAL,arg)=-1)perror(semctl setval error);arg.val=0;if(semctl(fullid,0,SETVAL,arg)=-1)perror(semctl setval error);/*定义定义P、V操作操作*/P.sem_num=0;P.sem_op=-1;P.sem_flg=SEM_UNDO;V.sem_num=0;V.sem_op=1;V.sem_flg=SEM_UNDO;/*创建并附接共享内存创建并附接共享内存*/shmid=shmget(IPC_PRIVATE,BUFSIZ,0666|IPC_CREAT);viraddr=(char*)s
30、hmat(shmid,0,0);2021-7-17linux进程间通信26while(chld=fork()=-1);/创建子进程创建子进程if(chld0)/父进程返回读信息并输出父进程返回读信息并输出 while(1) semop(fullid,&P,1);/对对fullid执行执行P操作操作printf(Your message is:n%s,viraddr);semop(emptyid,&V,1);/对对emptyid执行执行V操作操作if(strncmp(viraddr,end,3)=0)break; wait(0);/等待子进程终止等待子进程终止shmdt(viraddr);/断开
31、附接的共享内存断开附接的共享内存shmctl(shmid,IPC_RMID,0);/撤消共享内存和信号量集撤消共享内存和信号量集semctl(emptyid,IPC_RMID,0);semctl(fullid,IPC_RMID,0);printf(Parent ok!n);exit(0);2021-7-17linux进程间通信27else/子进程返回写信息到共享内存子进程返回写信息到共享内存while(1)semop(emptyid,&P,1);/对对emptyid执行执行P操作操作puts(Enter your text:);fgets(buffer,BUFSIZ,stdin);/键盘输入信
32、息键盘输入信息strcpy(viraddr,buffer); /写信息到共享内存中(覆盖方式)写信息到共享内存中(覆盖方式)semop(fullid,&V,1);/对对fullid执行执行V操作操作if(strncmp(viraddr,end,3)=0)sleep(1); /睡眠睡眠1秒,等待父进程将秒,等待父进程将end取走取走break;printf(Child ok!n);exit(0);2021-7-17linux进程间通信28运行结果:运行结果:由结果可以看出,子进程写到单缓冲区中的信息,父进程都依次取由结果可以看出,子进程写到单缓冲区中的信息,父进程都依次取出并输出了。出并输出了。
33、2021-7-17linux进程间通信292.利用信号量实现进程同步利用信号量实现进程同步例例4-11 设父进程创建一个子进程作为生产者,创建两个子进程作设父进程创建一个子进程作为生产者,创建两个子进程作为消费者,这三个子进程使用一个共享内存,该共享内存定义为为消费者,这三个子进程使用一个共享内存,该共享内存定义为具有具有5个变量的数组,每个变量表示一个缓冲区,缓冲区号为个变量的数组,每个变量表示一个缓冲区,缓冲区号为04。生产者进程依次往缓冲区。生产者进程依次往缓冲区04中写中写10个数据个数据110,两个读进,两个读进程依次从缓冲区程依次从缓冲区04中轮流取出这中轮流取出这10个数据。使用信号量实现进个数据。使用信号量实现进程读写缓冲区的同步和互斥。程读写缓冲区的同步和互斥。生产者消费者同步问题生产者消费者同步问题消费者消费者A进程进程消费者消费者B进程进程生产者进程生产者进程013242021-7-17linux进程间通信302.利用信号量实现进程同步利用信号量实现进程
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 2025-2030月饼行业市场深度分析及发展策略研究报告
- 2025-2030智慧医疗产业行业市场现状供需分析及投资评估规划分析研究报告
- 2025-2030新型纺织纤维行业市场现状供需分析及投资评估规划分析研究报告
- 2025-2030摩托车雨具行业市场现状供需分析及投资评估规划分析研究报告
- 2025-2030抽水泵市场发展现状分析及行业投资战略研究报告
- 2025-2030抗菌素项目可行性研究报告
- 2025-2030房地产投资产业行业市场现状供需分析及投资评估规划分析研究报告
- 2025-2030慢热锅行业市场深度分析及发展策略研究报告
- 2025-2030建筑石材产品入市调查研究报告
- 2025-2030床上夹克行业市场现状供需分析及重点企业投资评估规划分析研究报告
- 古代小说戏曲专题-形考任务2-国开-参考资料
- 中国艾滋病诊疗指南(2024版)解读 2
- 2024年新高考II卷高考政治+历史+地理试卷(真题+答案)
- GA/T 2133.1-2024便携式微型计算机移动警务终端第1部分:技术要求
- 六年级下册外研新版M7U1 He spent about twenty-one hours in space.教学设计
- 国家开放大学小学语文研究《送别组诗教学实录》教学策略评析
- 2023-2024学年辽宁省沈阳市南昌中学八年级(下)月考英语试卷(4月份)
- 国服中山装的设计特点及含义
- 木栓质生物降解与循环再利用
- 2024年河南省九年级中考数学模拟试卷(二)
- 消防控制室共用协议书
评论
0/150
提交评论