linux下多值信号量的操作探讨

时间:2022-09-22 12:35:11

linux下多值信号量的操作探讨

摘要:本文简单介绍了Linux下信号量通信机制的发展历史,信号量通信的特点,主要针对信号量的操作进行分析,其中包括创建信号量集合,修改信号量集合中某个信号量的值,如何获得信号量集合中某个信号量的值。文章最后给出多值信号量操作的实例,并且指出多值信号量操作时应该关注的重点问题。

关键词:信号量 进程间通信 操作

中图分类号:TP368.1 文献标识码:A 文章编号:1007-9416(2016)10-0240-01

1 Linux信号量通信机制发展史

Linux操作系统中有多种进程间通信方式。本文主要围绕信号量这种进程间通信方式进行阐述。信号量的概念最早由荷兰学者Edsger Dijkstra于1965年提出,目前已经发展成一种卓有成效的进程间通信机制。通过该机制可以有效的控制两个进程对共享资源的同步访问操作。

2 Linux单值信号量的操作

当信号量集合中只有一个信号量的时候,可以直接调用函数semop(int semid, struct sembuf *opsptr, size_t nops)来完成操作。其中第一个参数semid是信号量集合的标识符,即semget函抵葱谐晒后的返回值;第二个参数opsptr比较复杂,是struct sembuf类型的结构体,该结构体与我们对信号量的操作紧密相关。结构体原型为struct sembuf {short sem_num; short sem_op; short sem_flg; };有三个属性,第一个属性sem_num为信号量在信号量集合中的编号;第二个属性sem_op为当前信号量需要改变的值,如果该属性为正值,则在当前信号量基础之上增加sem_op,如果该属性为负值,则在当前信号量值的基础上减去sem_op,第三个属性为标志位,当取值为SEM_UNDO时,表示进程结束后由内核释放信号量发生改变的值。semop函数中的第三个参数表示对该信号量操作的次数。如果对该信号量操作一次,则参数nops取值为”1”,如果要操作两次,则该参数取值为”2”。如果要对某个信号量做多次操作的时候,需要把相关的操作封装到struct sembuf类型的数组中,即定义一个数组struct sembuf opbuf[2],然后对数组进行赋值opbuf[0].sem_num=0;opbuf[0].sem_op=1;opbuf[0].sem_flg=IPC_NOWAIT,这些数值表示对信号量集合中的第一个信号量进行加”1”操作,因为需要对该信号量进行两次操作,所以还需要对数组opbuf中的第二个元素进行赋值操作,即opbuf[1].sem_num=0;opbuf[1].sem_op=1;opbuf[1].sem_flg=IPC_NOWAIT。表示对信号量集合中的第一个信号量再次做加”1”操作。此时参数opstr取值为opbuf。

Semctl函数用来对信号量集合的属性进行操作。原型为semctl(int semid,int semnum,int cmd,../* union semun arg */);第一个参数semid为信号量集标识符,即semget的返回值,第二个参数semnum对应信号量在信号集合中的编号,第三个参数cmd是需要我们关注的参数,该参数与semctl函数完成的功能紧密相关,第四个参数是一个联合类型的变量,该变量中的值主要根据参数cmd的变化而发生改变。如果要得到单个信号量集合中的信号量的值,只需要给参数cmd赋值为GETVAL即可,此时,完全可以把第四个参数忽略掉。int semValue1=semctl(sem_id, 0, GETVAL);这行代码就表示得到标识符为sem_id的信号量集合中的编号为0的信号量的值,并且把该值保存在int类型的变量semValue1中。

3 Linux多值信号量的操作

如果信号量集合中有多个信号量,则需要分别调用代码int semValue1=semctl(sem_id, 0,GETVAL)多次。由此可见这种方式代码重复性较高,也比较麻烦。能否找到一种简单的方法直接得到该信号量集合中的所有信号量的值?答案是肯定的。这个时候需要用到semctl函数中的第四个参数,即union semun{int val;struct semid_ds *buf;ushort *array;struct seminfo *__buf; };需要先在代码中声明一下这个类型,然后定义此类型的变量,例如union semun semarg;再定义一个unsigned short 类型的数组,代码为unsigned shortreturnvalue[2]={0,0};该数组用来存放取出的信号量的值;第三步必须要给联合类型的变量semarg中的array属性赋值为第二步中定义的数组变量returnvalue,对应代码semarg.array=returnvalue;如果没有该步操作,相当于没有给semarg.array指针赋值,则程序运行结束后会收到SIGSEGV信号,从而出现段错误。之后可以调用semctl函数完成取值操作,此时,semctl函数中的第三个参数需要设置为GETALL,代码为semctl(sem_id,0,GETALL,semarg);便可以把标识符为sem_id的信号量集合中的所有信号量的值取出来,放入semarg变量中。

参考文献

[1]W.Richard Stevens,Stephen A. Rago 著 尤晋元等译.UNIX环境高级编程[M].北京:人民邮电出版社,2006,422-426.

[2]杨宗德.Linux高级程序设计[M].北京:人民邮电出版社,2012,273-285.

[3]杨水清.精通ARM嵌入式Linux系统开发[M].北京:电子工业出版社,2012,417-420.

收稿日期:2016-08-18

作者简介:许豪(1982―),男,河南南阳人,硕士,讲师,主要研究方向:嵌入式Linux开发,云计算相关。

上一篇:让孩子在球类活动中健康成长 下一篇:借助多媒体促进幼儿教育教学发展