許豪++單平平
摘要:本文簡單介紹了Linux下信號量通信機制的發(fā)展歷史,信號量通信的特點,主要針對信號量的操作進行分析,其中包括創(chuàng)建信號量集合,修改信號量集合中某個信號量的值,如何獲得信號量集合中某個信號量的值。文章最后給出多值信號量操作的實例,并且指出多值信號量操作時應(yīng)該關(guān)注的重點問題。
關(guān)鍵詞:信號量 進程間通信 操作
中圖分類號:TP368.1 文獻標(biāo)識碼:A 文章編號:1007-9416(2016)10-0240-01
1 Linux信號量通信機制發(fā)展史
Linux操作系統(tǒng)中有多種進程間通信方式。本文主要圍繞信號量這種進程間通信方式進行闡述。信號量的概念最早由荷蘭學(xué)者Edsger Dijkstra于1965年提出,目前已經(jīng)發(fā)展成一種卓有成效的進程間通信機制。通過該機制可以有效的控制兩個進程對共享資源的同步訪問操作。
2 Linux單值信號量的操作
當(dāng)信號量集合中只有一個信號量的時候,可以直接調(diào)用函數(shù)semop(int semid, struct sembuf *opsptr, size_t nops)來完成操作。其中第一個參數(shù)semid是信號量集合的標(biāo)識符,即semget函數(shù)執(zhí)行成功后的返回值;第二個參數(shù)opsptr比較復(fù)雜,是struct sembuf類型的結(jié)構(gòu)體,該結(jié)構(gòu)體與我們對信號量的操作緊密相關(guān)。結(jié)構(gòu)體原型為struct sembuf {short sem_num; short sem_op; short sem_flg; };有三個屬性,第一個屬性sem_num為信號量在信號量集合中的編號;第二個屬性sem_op為當(dāng)前信號量需要改變的值,如果該屬性為正值,則在當(dāng)前信號量基礎(chǔ)之上增加sem_op,如果該屬性為負值,則在當(dāng)前信號量值的基礎(chǔ)上減去sem_op,第三個屬性為標(biāo)志位,當(dāng)取值為SEM_UNDO時,表示進程結(jié)束后由內(nèi)核釋放信號量發(fā)生改變的值。semop函數(shù)中的第三個參數(shù)表示對該信號量操作的次數(shù)。如果對該信號量操作一次,則參數(shù)nops取值為”1”,如果要操作兩次,則該參數(shù)取值為”2”。如果要對某個信號量做多次操作的時候,需要把相關(guān)的操作封裝到struct sembuf類型的數(shù)組中,即定義一個數(shù)組struct sembuf opbuf[2],然后對數(shù)組進行賦值opbuf[0].sem_num=0;opbuf[0].sem_op=1;opbuf[0].sem_flg=IPC_NOWAIT,這些數(shù)值表示對信號量集合中的第一個信號量進行加”1”操作,因為需要對該信號量進行兩次操作,所以還需要對數(shù)組opbuf中的第二個元素進行賦值操作,即opbuf[1].sem_num=0;opbuf[1].sem_op=1;opbuf[1].sem_flg=IPC_NOWAIT。表示對信號量集合中的第一個信號量再次做加”1”操作。此時參數(shù)opstr取值為opbuf。
Semctl函數(shù)用來對信號量集合的屬性進行操作。原型為semctl(int semid,int semnum,int cmd,../* union semun arg */);第一個參數(shù)semid為信號量集標(biāo)識符,即semget的返回值,第二個參數(shù)semnum對應(yīng)信號量在信號集合中的編號,第三個參數(shù)cmd是需要我們關(guān)注的參數(shù),該參數(shù)與semctl函數(shù)完成的功能緊密相關(guān),第四個參數(shù)是一個聯(lián)合類型的變量,該變量中的值主要根據(jù)參數(shù)cmd的變化而發(fā)生改變。如果要得到單個信號量集合中的信號量的值,只需要給參數(shù)cmd賦值為GETVAL即可,此時,完全可以把第四個參數(shù)忽略掉。int semValue1=semctl(sem_id, 0, GETVAL);這行代碼就表示得到標(biāo)識符為sem_id的信號量集合中的編號為0的信號量的值,并且把該值保存在int類型的變量semValue1中。
3 Linux多值信號量的操作
如果信號量集合中有多個信號量,則需要分別調(diào)用代碼int semValue1=semctl(sem_id, 0,GETVAL)多次。由此可見這種方式代碼重復(fù)性較高,也比較麻煩。能否找到一種簡單的方法直接得到該信號量集合中的所有信號量的值?答案是肯定的。這個時候需要用到semctl函數(shù)中的第四個參數(shù),即union semun{int val;struct semid_ds *buf;ushort *array;struct seminfo *__buf; };需要先在代碼中聲明一下這個類型,然后定義此類型的變量,例如union semun semarg;再定義一個unsigned short 類型的數(shù)組,代碼為unsigned shortreturnvalue[2]={0,0};該數(shù)組用來存放取出的信號量的值;第三步必須要給聯(lián)合類型的變量semarg中的array屬性賦值為第二步中定義的數(shù)組變量returnvalue,對應(yīng)代碼semarg.array=returnvalue;如果沒有該步操作,相當(dāng)于沒有給semarg.array指針賦值,則程序運行結(jié)束后會收到SIGSEGV信號,從而出現(xiàn)段錯誤。之后可以調(diào)用semctl函數(shù)完成取值操作,此時,semctl函數(shù)中的第三個參數(shù)需要設(shè)置為GETALL,代碼為semctl(sem_id,0,GETALL,semarg);便可以把標(biāo)識符為sem_id的信號量集合中的所有信號量的值取出來,放入semarg變量中。
參考文獻
[1]W.Richard Stevens,Stephen A. Rago 著 尤晉元等譯.UNIX環(huán)境高級編程[M].北京:人民郵電出版社,2006,422-426.
[2]楊宗德.Linux高級程序設(shè)計[M].北京:人民郵電出版社,2012,273-285.
[3]楊水清.精通ARM嵌入式Linux系統(tǒng)開發(fā)[M].北京:電子工業(yè)出版社,2012,417-420.
收稿日期:2016-08-18
作者簡介:許豪(1982—),男,河南南陽人,碩士,講師,主要研究方向:嵌入式Linux開發(fā),云計算相關(guān)。