
学术论坛
linux下多值信号量的操作探讨
许豪单平平
(南阳理工学院河南南阳473004)
数事其本与流用
摘要:本文简单介绍了Linux下信号量通信机制的发展历史,信号量通信的特点,主要针对信号量的操作进行分析,其中包括创建信号量集合,修改信号量集含中某个信号量的值,加何获得信号量集含中某个信号量的值。文章最后给出多值信号量操作的实例,并且指出多值信号量操作时应该关注的重点问题,
关键词:信号量进程间通信操作
中图分类号:TP368.1
1Linux信号量通信机制发展史
文献标识码:A
Liux操作系统中有多种进程间通信方式。本文主要围绕信号量这种进程间通信方式进行阐述。信号量的概念最早由荷兰学者 EdsgerDikstra于1965年提出,目前已经发展成一种卓有成效的进程间通信机制。通过该机制可以有效的控制两个进程对共享资源的同步访间操作。
2Linux单值信号量的操作
当信号量集合中只有一个信号量的时候,可以直接调用函数 semop(int semid,struct sembuf *opsptr,size_t nops)来完成操作。其中第一个参数semid是信号量集合的标识符,即semget函数执行成功后的返回值,第二个参数opsptr比较复杂,是structsembuf 类型的结构体,该结构体与我们对信号量的操作紧密相关。结构体原型为struct sembuf ishort sem_num; short sem_op; short sem_flg;,有三个属性,第一个属性sem_num为信号量在信号量集合中的编号,第二个属性semLop为当前信号量需要改变的值,如果该属性为正值,则在当前信号量基础之上增加semLop,如果该属性为负值,则在当前信号量值的基础上减去sem_op,第三个属性为标志位,当取值为SEMLUNDO时,表示进程结束后由内核释放信号量发生改变的值。semop函数中的第三个参数表示对该信号量操作的次数。如果对该信号量操作一次,则参数nops取值为"1",如果要操作两次,则该参数取值为“2”。如果要对某个信号量微多次操作的时候,需要把相关的操作封装到structsembuf类型的数组中,即定义一个数组struct sembuf opbuf[2],然后对数组进行赋值opbuf[0] sem_num=0,opbuf[o].sem_op=l,opbuf[o]. semLflg=IPC_NOWAIT,这些数值表示对信号量集合中的第一个信号量进行加1"操作,因为需要对该信号量进行两次操作,所以还需要对数组opbuf中的第二个元素进行账值操作,即opbuf1, sem_ num= 0, opbuf[1]. sem_ op= 1 , opbuf[1] . semLflg=IPC_NOWAIT。表示对信号量集合中的第一个信号量再次做加1"操作。此时参数opstr取值为opbuf。
Semctl函数用来对信号量集合的属性进行操作。原型为semctl(int semid,int semnum,int cmd,.-/ union semun arg +/) 第一个参数semid为信号量集标识符,即semget的返回值,第二个参数semnum对应信号量在信号集合中的编号,第三个参数cmd是需要我们关注的参数,该参数与semctl函数完成的功能紧密相关,第四个参数是一个联合类型的变量,该变量中的值主要根据参数cmd的
收移日期:2016-08-18
文章编号:1007-9416(2016)10-0240-0)
变化而发生改变。如果要得到单个信号量集合中的信号量的值,只需要给参数cmd赋值为GETVAL即可,此时,完全可以把第四个多数忽略掉。int semValuel=semctl(sem_id,0,GETVAL)这行代码就表示得到标识符为sem_id的信号量集合中的编号为0的信号量
的值,并且把该值保存在int类型的变量semValue1中。 3Linux多值信号量的操作
如果信号量集合中有多个信号量,则需要分别调用代码iⅡt semValuel=semctl(sem_id,0,GETVAL)多次由此可见这种方式代码重复性较高,也比较麻烦。能否找到一种简单的方法直接得到该信号量集合中的所有信号量的值?答案是背定的。这个时候需要用到semctl函数中的第四个参数,即union semuntintval;struct semid_dsbuf,ushort*arraystructseminfo+_buf,I,需要先在代码中声明一下这个类型,然后定义此类型的变量,例如union semunsemarg,再定义一个unsignedshort类型的数组,代码为 unsigned shortreturnvalue[2]={0,o:,该数组用来存放取出的信号量的值,第三步必须要给联合类型的变量semarg中的array属性赋值为第二步中定义的数组变量returnvalue,对应代码semarg, array=returnvalue;如果没有该步操作,相当于没有给semarg.ar-ray指针赋值,则程序运行结束后会收到SIGSEGV信号,从而出现段错误。之后可以调用semctl函数完成取值操作,此时,semctl函数中的第三个参数需要设置为GETALL,代码为semctl(sem_id,0, GETALLsemarg),便可以把标识符为sem_id的信号量集合中的所
有信号量的值取出来,放人semarg变量中。参考文献
[1Jw.Richard Stevens,Stephen ARago 著尤晋元等译.UNIX环境高级编程[M7北京:人民邮审出版社,2006.422-426
[2]稳宗德.LinuX高级程序设计[M].北京:人民邮电出版社,2012, 273-285.
[3]杨水清.精通ARM嵌入式LInuX系统开发[M].北京:电子工业出版社.2012,417420.
作者简介:许豪(1982一),男,河南南阳人,硕士,讲师,主要研究方向:嵌入式Linux开发,云计算相关 240
万方数据