linux程序間同步之POSIX訊號量

2021-08-21 03:12:15 字數 3008 閱讀 8570

《閱讀linux系統程式設計手冊筆記》

posix訊號量跟system v訊號量一樣,都是用於程序和執行緒同步對同享資源的訪問。訊號量(posix,system v)是乙個整數,其值是不能小於0的。

posix訊號量主要分為:命名訊號量、未命名訊號量。

首先先介紹命名訊號量。

先來看看命名訊號量的主要api:

1. sem_open()

#include #include #include sem_t *semopen( const char *name, int oflag .../*mode_t mode, unsigned int value */) //成功返回訊號量指標,失敗返回sem_failed
引數:

name:標識訊號量

oflag:位掩碼。

if oflag == 0 then 訪問乙個既有的訊號量

if oflag == o_creat and 訪問的訊號量不存在 then 建立乙個新的訊號量

if oflag == o_creat | o_excl and 訊號量已經存在 then 失敗

如果用來開啟乙個存在的訊號量,上面兩個引數就夠了,但是,當指定了o_creat,則還需要mode和value。

mode:位掩碼。指定了新訊號量上的許可權

value:無符號整數,指定了訊號量的初始值

susv3聲稱在sem_open()的返回值指向的sem_t變數的副本上執行操作時的結果時未定義的。換言之,下面的操作不被允許!

sem_t *sp, sem2;

sp = sem_open(...);

sem2 = *sp;

sem_wait(&sem2)

通過fork()建立的子程序會繼承其父程序開啟的所有命名訊號量的引用。

2.sem_close()

#include int sem_close(sem_t *sem);//成功返回0,失敗返回-1
當乙個程序開啟乙個命名訊號量時,系統會記錄程序和訊號量之間的關聯關係。sem_close()會終止這種關係,釋放系統為該程序關聯到該訊號量之上的所有資源,並遞減引用該訊號量的程序數。

3.sem_unlink()

#include int sem_unlink(const char *name);

/*成功返回0,失敗返回-1*/

sem_unlink()函式刪除通過name標識的訊號量並將其標記為一旦所有的程序都使用完這個訊號量後就摧毀該訊號量。也就是說,這個函式不一定是馬上起作用的,當所有的程序都close了,該訊號量才會被摧毀。

4.sem_wait()

#include int sem_wait(sem_t *sem);

/*成功返回0,失敗返回-1*/

功能描述:

if 訊號量值 > 0 then 函式立即返回,訊號量值遞減

if 訊號量值 == 0 then 函式阻塞直到訊號量值大於0

如果乙個阻塞的sem_wait()被訊號處理器中斷了,就會返回eintr錯誤,不管在使用sigaction()時是否指定了sa_restart標記。

*sem_wait的其他版本

#include int sem_trywait(sem_t *sem);//成功返回0,失敗返回-1。非阻塞版本,如果不能遞減,返回失敗並設定errno = eagain

int sem_timedwait(sem_t *sem,comst struct timespec *abc_timeout);//成功返回0,失敗返回-1。當超時不能遞減該訊號量時,返回失敗並且設定errno = etimeout

5.sem_post

#include int sem_post(sem_t *sem);

/*成功返回0,失敗返回-1*/

如果有多個程序在sem_wait()中阻塞了,怎麼辦?

如果這些程序的排程採用的是預設的迴圈時間分享策略,那麼哪個程序被喚醒是不確定的。

susv3規定,如果程序或者執行緒執行在實時排程策略下,那麼優先順序最高的優先喚醒。

6.sem_getvalue()

#include int sem_getvalue(sem_t *sem, int *sval);

/*成功返回0,失敗返回-1*/

注意:sem_getvalue()返回得到的值sval可能已經過時!

未命名訊號量是型別為sem_t並儲存在應用程式分配的記憶體的變數。通過將這個訊號量放在由幾個程序或執行緒共性的記憶體區域中就能使這個訊號量對這些程序或者執行緒可用。

通過一張圖看看命名訊號量和未命名訊號量api的區別:

/*成功返回0,失敗返回-1*/

引數描述:

value:訊號量初始化的值

if pshared == 0 then 訊號量在程序中的執行緒間共享。sem被指定成乙個全域性變數或者在堆上的乙個變數位址。

if pshared !=0 then 訊號量在程序間共享,sem必須是共享記憶體區域。

susv3規定乙個已經初始化的未命名訊號量進行初始化操作導致未定義的行為。換言之,必須要將應用程式設計為只有第乙個程序或者執行緒來呼叫sem_init()以初始化乙個訊號量。

2.sem_destory()

#include int sem_destory(sen_t *sem);

/*成功返回0,失敗返回-1*/

linux 程序間同步

程序間也可以使用互斥鎖,來達到同步的目的。但應在pthread mutex init初始化之前,修改其屬性為程序間共享。mutex的屬性修改函式主要有以下幾個。pthread mutexattr t型別 用於定義mutex鎖的屬性 pthread mutexattr init函式 初始化乙個mute...

linux程序間的同步方法

程序間通訊 ipc 方法主要有以下幾種 管道 fifo 共享記憶體 訊息佇列 訊號 1.管道中還有命名管道和非命名管道 即匿名管道 之分,非命名管道 即匿名管道 只能用於父子程序通訊,命名管道可用於非父子程序,命名管道就是fifo,管道是先進先出的通訊方式 2.訊息佇列是用於兩個程序之間的通訊,首先...

程序執行緒間同步

一 posix訊息佇列 通過固定名稱來建立和引用訊息佇列 1.可以認為是乙個訊息鍊錶,有足夠的許可權的執行緒可以往佇列中放置和獲取訊息。2.可指定優先順序 在空佇列放置訊息時候能夠產生乙個訊號或啟動乙個執行緒 3.建立訊息佇列mq open mq close 關閉 並不刪除 mq unlink 刪除...