命名訊號量
命名訊號量:這種訊號量擁有一個名字。透過使用相同的名字呼叫sem_open(),不相關的程序能夠訪問同一個訊號量
開啟一個命名訊號量
sem_t *sem_open(const char *name, int oflag, ...
/* mode_t mode, unsigned int value*/);
- 引數:
-
name: 訊號量的名字,斜線開頭,如
/demo_sem
-
oflag: 控制訊號量的開啟方式
-
O_CREAT
: 如果訊號量不存在,則建立一個新訊號量 -
O_EXCL
: 配合 O_CREAT 一起使用時,確保呼叫程序是建立者預設是可讀寫的
-
-
mode: 引數指定訊號量的許可權
-
value: 該引數指定訊號量的初始值
mode和value兩個引數只有在指定O_CREAT時才使用
-
- 返回值:
成功返回訊號量,失敗返回SEM_FAILED
關閉一個命名訊號量
int sem_close(sem_t *sem);
當一個程序開啟一個命名訊號量時,系統會記錄程序與訊號量之間的關聯關係。sem_close()函式會終止這種關聯關係(即關閉訊號量),釋放系統為該程序關聯該訊號量之上的所有資源,並遞減引用該訊號量的程序數
關閉訊號量,不是刪除這個訊號量,就像是,關閉檔案描述符,不會刪除檔案一樣
刪除一個命名訊號量
int sem_unlink(const char *name);
sem_unlink()函式刪除透過 name 標識的訊號量並將訊號量標記成一旦所有程序都使用完這個訊號量時就銷燬該訊號量(這可能立即發生,前提是所有開啟過該訊號量的程序都已經關閉了這個訊號量)。
修改訊號量的值
等待一個訊號量
sem_wait()函式會遞減(減小1)sem引用的訊號量的值
int sem_wait(sem_t *sem);
若是訊號量的值大於0,則會立即減1,等於0,則會一直阻塞,直到訊號量增加
表示 程序正在等待一個資源
釋出一個訊號量
sem_post()函式遞增(增加1)sem引用的訊號量的值。
int sem_post(sem_t *sem);
若訊號量的值等於0,並且其他程序正在等待這個訊號量,那麼當釋出訊號量後,等待的程序會被喚醒,如果有多個程序等待,則不保證喚醒順序
表示 程序釋放了一個資源
獲取訊號量的值
sem_getvalue()函式將 sem 引用的訊號量的當前值透過sval指向的int變數返回
int sem_getvalue(sem_t *sem, int *sval); // 獲取訊號量的值可能在獲取後又被修改了
如果一個或多個程序(或執行緒)當前正在阻塞以等待遞減訊號量值,那麼sval 中的返回值將取決於實現。SUSv3允許兩種做法:0或一個絕對值等於在sem_wait()中阻的等待者數目的負數。Linux和其他一些實現採用了第一種行為,而另一些實現則採用了後一種行為。
未命名訊號量(基於記憶體的訊號量)
未命名訊號量:這種訊號量沒有名字,相反,它位於記憶體中一個預先商定的位置處。未命名訊號量可以在程序之間或一組執行緒之間共享。當在程序之間共享時,訊號量必須位於一個共享記憶體區域中(System V、POSIX或mmap())。當線上程之間共享時,訊號量可以位於被這些執行緒共享的一塊記憶體區域中(如在堆上或在一個全域性變數中)
初始化一個未命名訊號量
int sem_init(sem_t *sem, int pshared, unsigned int value);
引數 pshared
表示該訊號量是在程序間共享還是執行緒間共享
pshared = 0
表示在 執行緒間共享,則訊號量分配在全域性變數或者堆上等地址處,在程序終止後銷燬pshared = 1
表示在 程序間共享,則訊號量分配在一片共享記憶體區域(共享記憶體物件或者共享記憶體對映),fork呼叫會使子程序繼承父程序的共享記憶體區域,這樣兩者就能透過訊號量進行同步了
銷燬一個未命名訊號量
int sem_destroy(sem_t *sem);
sem_destroy()函式將銷燬訊號量 sem,其中 sem 必須是一個之前使sem_init()進行初始化的未命名訊號量。只有在不存在程序或執行緒在等待一個訊號量時才能夠安全銷燬這個訊號量。
需要注意的是,訊號量銷燬的時機,執行緒間共享,則要在程序終止前銷燬,程序間共享,則要在沒有程序引用訊號量以及刪除共享記憶體對映前銷燬