Linux下訊號燈的使用
作者:楊碩,講師。
一、訊號燈簡介:
Linux支援系統5的訊號燈(semaphore),是一種程式間通訊的方式,只不過它和管道、FIFO或者共享記憶體等不一樣,訊號燈主要用於同步或者互斥對共享資源的訪問,它的發明來源於火車執行系統中的“訊號燈”,利用訊號燈可以實現 “PV操作”這種程式間同步機制。P操作是獲得資源,將訊號燈的值減1,如果結果不為負則執行完畢,程式獲得資源,否則程式睡眠以等待資源別的程式釋放資源;V操作則是釋放資源,給訊號燈的值加1,釋放一個因執行P操作而等待的程式。
二、訊號燈的兩種型別
1、二值訊號燈:
最簡單的訊號燈形式,訊號燈的值只能取0或1,類似於互斥鎖。
雖然二值訊號燈能夠實現互斥鎖的功能,但兩者的關注內容不同。訊號燈強調共享資源,只要共享資源可用,其他程式同樣可以修改訊號燈的值;互斥鎖更強調程式,佔用資源的程式使用完資源後,必須由程式本身來解鎖。
2、 計數訊號燈:
訊號燈的值可以取任意非負值(當然受核心本身的約束),用來統計資源,其值就代表可用資源的個數。
三、Linux下對訊號燈的操作
1、 開啟或建立訊號燈
對應的系統呼叫:
#include
#include
#include
int semget(key_t key, int nsems, int semflg);
第一個引數key是一個鍵值,訊號燈集的描述符就由系統範圍內唯一的一個鍵值生成。
key可以由ftok函式生產:
#include
#include
key_t ftok(const char *pathname, int proj_id);
ftok返回與系統中的路徑pathname相對應的一個鍵值
nsems是訊號燈集中訊號燈的個數,其最大值取決於具體的系統,如果是0,則代表訪問已存在的訊號燈集。
semflg是一些標誌位,它是IPC_CREAT、IPC_EXCL、IPC_NOWAIT三者與訪問許可權或的結果,訪問許可權一般都是0600,代表只有訊號燈集的屬主才對訊號燈集有讀寫的許可權。
semget()如果執行成功,返回與key對應的訊號燈集描述字(非負整數,存在於記憶體之中),失敗返回-1,並將錯誤碼置於errno全域性變數中。
2、操作訊號燈
linux可以增加或減小訊號燈的值,相應於對共享資源的釋放和佔有。
對應的系統呼叫:
#include
#include
#include
int semop(int semid, struct sembuf *sops, unsigned nsops);
semop系統呼叫可以實現對由semid標誌的訊號燈集中的某一個指定訊號燈的一系列操作。
semid即是semget返回的訊號燈描述字。
sops是指向結構體sembuf的指標,可以是這種型別的結構體陣列的頭指標,陣列的每一個sembuf結構都刻畫一個在特定訊號燈上的操作。
nsops為sops指向陣列的大小(有幾個sembuf結構體)。
sembuf結構體定義如下:
struct sembuf
{
unsigned short sem_num; /* semaphore number */
short sem_op; /* semaphore operation */
short sem_flg; /* operation flags */
};
sem_num對應訊號燈集中的訊號燈,0代表第一個訊號燈。
sem_op的值決定了對sem_num指定的訊號燈的三種不同操作:
● sem_op = 0,呼叫者阻塞等待直到訊號燈的值等於0時返回。可以用來測試共享資源是否已用完。
● sem_op > 0,代表程式要申請-sem_op個共享資源。
如果訊號燈值sem_val > abs(sem_op),則sem_val = sem_val-abs(sem_op);
否則呼叫程式睡眠直到sem_val>=abs(sem_op)。當然如果sem_flg指定為IPC_NOWAIT,則呼叫程式立即返回。
● sem_op > 0,代表程式要釋放sem_op數量的共享資源。也就是V操作。
sem_flg可取0,IPC_NOWAIT以及SEM_UNDO兩個標誌。
● 0代表阻塞呼叫
● IPC_NOWAIT代表非阻塞呼叫
● 如果設定了SEM_UNDO標誌,那麼在程式結束時,相應的操作將被取消,這是比較重要的一個標誌位。如果設定了該標誌位,那麼在程式沒有釋放共享資源就退出時,核心將代為釋放。如果為一個訊號燈設定了該標誌,核心都要分配一個 sem_undo結構來記錄它,為的是確保以後資源能夠安全釋放。事實上,如果程式退出了,那麼它所佔用就釋放了,但訊號燈值卻沒有改變,此時,訊號燈值反映的已經不是資源佔有的實際情況,在這種情況下,問題的解決就靠核心來完成。這有點像殭屍程式,程式雖然退出了,資源也都釋放了,但核心程式表中仍然有它的記錄,此時就需要父程式呼叫waitpid來解決問題了。
semop呼叫成功返回0,失敗返回-1,並將錯誤碼置於errno全域性變數中。
semop可以同時操作多個訊號燈,在實際應用中,對應多種資源的申請或釋放。semop保證操作的原子性,這一點尤為重要。尤其對於多種資源的申請來說,要麼一次性獲得所有資源,要麼放棄申請,要麼在不佔有任何資源情況下繼續等待,這樣,一方面避免了資源的浪費;另一方面,避免了程式之間由於申請共享資源而造成死鎖。
3、 獲得或設定訊號燈屬性:
對應的系統呼叫:
#include
#include
#include
int semctl(int semid, int semnum, int cmd, union semun arg);
semctl透過具體的cmd操作由semid標誌的訊號燈集上的由semnum指定的訊號燈。
常用的cmd有一下幾個:
● IPC_STAT 獲取訊號燈資訊,資訊由arg.buf返回;
● GETVAL 返回semnum所代表訊號燈的值;
● SETVAL 設定semnum所代表訊號燈的值為arg.val;
● IPC_RMID 刪除semnum所代表的訊號燈
使用者需要自己定義聯合體semun如下:
union semun {
int val; /* Value for SETVAL */
struct semid_ds *buf; /* Buffer for IPC_STAT, IPC_SET */
unsigned short *array; /* Array for GETALL, SETALL */
struct seminfo *__buf; /* Buffer for IPC_INFO (Linux-specific) */
};
semctl呼叫成功返回0,失敗返回-1,並將錯誤碼置於errno全域性變數中。
四、利用訊號燈實現PV操作
1、P操作:申請資源
這裡我們封裝一個函式down():
/*
* function: ask for resource, P operation
* parameter: sem_id : identifier of a semaphore set;
sem_num : semaphore number
* return value: none
*/
void down(int sem_id, int sem_num)
{
struct sembuf op;
op.sem_num = sem_num;
op.sem_op = -1;
op.sem_flg = 0;
semop(sem_id, &op, 1);
}
2、V操作:釋放資源
這裡我們封裝一個函式up():
/*
* function: free resource, V operation
* parameter: sem_id : identifier of a semaphore set;
sem_num : semaphore number
* return value: none
*/
void up(int sem_id, int sem_num)
{
struct sembuf op;
op.sem_num = sem_num;
op.sem_op = 1;
op.sem_flg = 0;
semop(sem_id, &op, 1);
}
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/24790158/viewspace-1042129/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- linux 下的訊號量引數Linux
- Linux 下的程式間通訊:套接字和訊號Linux
- Linux程式間通訊——使用訊號量Linux
- Linux訊號機制與訊號處理Linux
- 城市交通訊號燈高畫質動態桌布
- linux中的兩個非常重要的訊號:SIGALRM訊號和SIGCHID訊號LinuxGC
- Linux 未決訊號集與訊號遮蔽字Linux
- linux 訊號機制Linux
- Linux 訊號量大全Linux
- linux訊號表(轉)Linux
- system -v 訊號量的使用
- Linux 下的程式間通訊:使用管道和訊息佇列Linux佇列
- Linux中訊號量的實現Linux
- Linux中的System V訊號量Linux
- linux訊號的阻塞和未決Linux
- Django | 訊號使用思考Django
- Linux系統下使用pppd撥號上網Linux
- 在Linux下使用ISDN撥號上網 (轉)Linux
- linux 訊號與處理Linux
- Linux訊號簡介(轉)Linux
- linux程式間通訊-----訊號總結Linux
- Linux下應用程式開發:QT的訊號與槽機制(轉)LinuxQT
- linux中的訊號處理與SROPLinux
- Linux Shell的訊號trap功能細節Linux
- Linux的kill命令與訊號控制(轉)Linux
- 訊號課組(一) 訊號與系統 Part 0 MATLAB在訊號與系統中的使用Matlab
- 從未卜先知的訊號燈說起,阿里城市大腦的智慧交通實踐阿里
- Linux系統程式設計之訊號中斷處理(下)Linux程式設計
- Jtti:linux下訊號量和互斥鎖有哪些區別?JttiLinux
- 路由器光訊號閃紅燈是什麼意思 路由器突然閃紅燈上不了網路由器
- Linux訊號捕捉之sigactionLinux
- Linux SIGCHLD訊號處理LinuxGC
- Linux--訊號阻塞與遮蔽Linux
- Linux訊號處理機制Linux
- Linux訊號(signal)機制Linux
- linux系統程式設計之訊號(一):中斷與訊號Linux程式設計
- Linux下鍵盤燈開啟和關閉的指令碼Linux指令碼
- linux系統程式設計之訊號(五):訊號集操作函式,訊號阻塞與未決Linux程式設計函式