淺析Unix信號量知識
在Unix信號量機制實現(xiàn)之前,通常采用加鎖文件的方法。信號量(Semaphore),有時被稱為信號燈,是在多線程環(huán)境下使用的一種設(shè)施,是可以用來保證兩個或多個關(guān)鍵代碼段不被并發(fā)調(diào)用。在進入一個關(guān)鍵代碼段之前,線程必須獲取一個信號量;一旦該關(guān)鍵代碼段完成了,那么該線程必須釋放信號量。
其它想進入該關(guān)鍵代碼段的線程必須等待直到***個線程釋放信號量。為了完成這個過程,需要創(chuàng)建一個信號量VI,然后將Acquire Semaphore VI以及Release Semaphore VI分別放置在每個關(guān)鍵代碼段的首末端。確認(rèn)這些信號量VI引用的是初始創(chuàng)建的信號量。
系統(tǒng)調(diào)用semop用來對Unix信號量集合中的一個或多個信號量進行操作,操作命令由用戶提供的操作結(jié)構(gòu)數(shù)組來定義,該結(jié)構(gòu)如下:
- struct sembuf{
- short sem_num; /*信號量在集合中的下標(biāo)*/
- short sem_op; /*操作值*/
- short sem_flg; /*操作標(biāo)志*/
- };
系統(tǒng)從用戶地址空間讀Unix信號量操作結(jié)構(gòu)數(shù)組,并核實信號量下標(biāo)的合法性及進程是否具備讀或修改信號量所必需的權(quán)限。若權(quán)限不夠則調(diào)用失敗;若進程必須睡眠,則它將已操作過的信號量恢復(fù)為該系統(tǒng)調(diào)用開始時的值,然后它就睡眠,直到它等待的事件發(fā)生時再重新執(zhí)行該系統(tǒng)調(diào)用。
由于系統(tǒng)將操作數(shù)組保存在一個全局?jǐn)?shù)組中,因此若它必須重新執(zhí)行該調(diào)用的話,它必須重新從用戶空間讀該數(shù)組。這樣,操作按原語方式執(zhí)行--或一次做完或根本不做。
系統(tǒng)根據(jù)操作值來改變信號量的值:
①若操作值為正,系統(tǒng)就增加信號量的值并喚醒所有等待信號量增值的進程;
②若操作值是0,系統(tǒng)就檢查信號量的值:如果為0,就繼續(xù)數(shù)組中的其它操作;否則把等待信號量的值為0的睡眠進程數(shù)加1,然后睡眠;
③若操作值為負(fù)且其絕對值不超過信號量的值,系統(tǒng)就把操作值(一個負(fù)數(shù))加到信號量值上,如果結(jié)果為0則系統(tǒng)就喚醒所有等待信號量的值為0的睡眠進程;
④若信號量的值小于操作值的絕對值,系統(tǒng)就讓進程睡眠在"等待信號量增值"這一事件上。
當(dāng)進程在Unix信號量操作過程中睡眠時,它睡眠在可中斷級上,因此當(dāng)它接收到軟中斷信號時就被喚醒了。用戶可在操作標(biāo)志中設(shè)置IPC_NOWAIT標(biāo)志以防止進程睡眠。
如果進程執(zhí)行了一個信號量操作,鎖住了某些資源,卻沒有恢復(fù)信號量的值就退出了(如收到kill信號),那么就可能出現(xiàn)危險情況。為了避免這類問題,用戶可在操作標(biāo)志中設(shè)置SEM_UNDO標(biāo)志。當(dāng)進程退出時,系統(tǒng)便撤除該進程做過的每個信號量操作的影響。
值得指出的是,當(dāng)你使用兩個或多個Unix信號量時,死鎖總是可能的,系統(tǒng)并不能檢查多個信號量間的死鎖。
本文所用算法及調(diào)用格式均已在SCOUNIX3.2、SCOOpenSever3.X及5.X上運行通過。
【編輯推薦】