linux下訊號量及其SEM_UNDO標誌
AT&T的貝爾實驗室,對Unix早期的程序間通訊進行了改進和擴充,形成了"system V IPC",其通訊程序主要侷限在單個計算機內。IPC物件指的是共享記憶體(share memory)、訊息佇列(message queue)和訊號燈集(semaphore)。
訊號燈(semaphore),也叫訊號量。
本質;一種資料操作鎖(本身是一個計數器,是對臨界資源的保護),它本身不具有資料交換的功能,而是通過控制其他的通訊資源(檔案,外部裝置)來實現程序間通訊,它本身只是一種外部資源的標識。訊號量在此過程中負責資料操作的互斥、同步等功能。
當請求一個使用訊號量來表示的資源時,程序需要先讀取訊號量的值來判斷資源是否可用。大於0,資源可以請求,等於0,無資源可用,程序會進入睡眠狀態直至資源可用。當一個程序不再使用一個訊號量控制的共享資源時,訊號量的值+1,對訊號量的值進行的增減操作為原子操作,這是由於訊號量主要的作用是維護資源的互斥或多程序的同步訪問。而訊號量的建立以及初始化上,不能保證操作為原子操作。
使用訊號量的原因:為了防止出現因多個程式同時訪問一個共享資源而引發的一系列問題,它可以通過生成並使用令牌來授權,在任意時刻只能有一個執行執行緒訪問程式碼的臨界區域。臨界區域是指執行資料更新的程式碼需要獨佔式地執行。而訊號量就可以提供這樣的一種訪問機制,讓一個臨界區同一時間只有一個執行緒在訪問它,也就是說訊號量是用來協調程序對共享資源的訪問的。
缺點:建立和初始化分離。
訊號燈是不同程序間或一個給定程序內部不同執行緒間同步的機制。System V的訊號燈是一個或者多個訊號燈的一個集合。其中的每一個都是單獨的計數訊號燈。System V 訊號燈由核心維護。主要函式semget,semop,semctl。
1、semget函式:建立一個訊號量集物件(得到一個訊號量集識別符號)
函式原型:int semget(key_t key,int nsems,int semflg)
key:由ftok()函式的得到
nsems:建立訊號量集中訊號的個數
semflg:
IPC_CREAT:若核心中不存在鍵值與key相等的訊號量集,則建立,否則,返回此訊號量集的識別符號
IPC_EXCL:單獨使用無意義
IPC_CREAT | IPC_EXCL :建立一個新的訊號量集並返回訊號量集的識別符號,否則,返回-1.
返回值:成功返回訊號量集的識別符號。失敗返回-1.
2、semctl函式:在指定的訊號集或訊號集內的某個訊號上執行操作控制
函式原型:int semctl(int semid,int semnum,int cmd,union semun arg)
semid: 訊號量集識別符號
semnum:訊號量集陣列上的下標,表示某一個訊號量
arg:
union semun {
short val; /*SETVAL用的值*/
struct semid_ds* buf; /*IPC_STAT、IPC_SET用的semid_ds結構*/
unsigned short* array; /*SETALL、GETALL用的陣列值*/
struct seminfo *buf; /*為控制IPC_INFO提供的快取*/
} arg;
3、semop函式:對訊號量進行P,V操作(本文的重點)
P操作負責把當前程序由執行狀態轉換為阻塞狀態,直到另外一個程序喚醒它。操作為:申請一個空閒資源(把訊號量減1),若成功,則退出;若失敗,則該程序被阻塞;
V操作負責把一個被阻塞的程序喚醒,它有一個引數表,存放著等待被喚醒的程序資訊。操作為:釋放一個被佔用的資源(把訊號量加1),如果發現有被阻塞的程序,則選擇一個喚醒之。
semop函式原型如下:
int semop(int semid, struct sembuf *sops, unsigned nsops);
semop操作中:sembuf結構的sem_flg成員可以為0、IPC_NOWAIT、SEM_UNDO 。為SEM_UNDO時,它將使作業系統跟蹤當前程序對這個訊號量的修改情況,如果這個程序在沒有釋放該訊號量的情況下終止,作業系統將自動釋放該程序持有的。
sembuf結構的sem_flg成員為SEM_UNDO時,它將使作業系統跟蹤當前程序對這個訊號量的修改情況,如果這個程序在沒有釋放該訊號量的情況下終止,作業系統將自動釋放該程序持有的訊號量,從而使另外一個程序可以繼續工作,防止其他程序因為得不到訊號量而發生【死鎖現象】。為此一般建議使用SEM_UNDO。
測試程式碼:
sem.h
sem.c
semtest.c
執行結果:
本文出自 “緣去即成幻” 部落格,請務必保留此出處http://liu153.blog.51cto.com/10820414/1829429