使用System V訊號量實現多執行緒互斥

2021-08-25 20:42:15 字數 2226 閱讀 9863

posix thread中提供了非常強大的執行緒互斥機制, 如 pthread_mutex_***x / pthread_cond_***x 以及semaphore(sem_wait/sem_post)等。在同一程序內的多執行緒程式設計非常方便靈活。但對於跨程序的執行緒互斥問題就變得麻煩了。

其實主流的linux在核心中也實現了system v的ipc, 在跨程序的執行緒互斥方面實現起來更加簡單。當然,同一程序容器內的多執行緒也可以使用。

semget的man page:

如果是在同一程序或者親緣程序內使用

#include #include int semid = semget( ipc_private, 1, 0);

這樣就建立了乙個無名訊號量集合,其中semget的第2個引數表示這個訊號量集合中有1個訊號量。

而對於非親緣關係的多程序內線程使用的訊號量,則一般這樣建立

#include #include key_t ipckey = ftok("/tmp/foo", 42);

int semid = semget( ipckey, 1, ipc_creat | 0666);

ftok函式用於建立system v 的 ipc key, 其中第乙個引數必須是存在的檔案路徑且具備可訪問許可權。

第2個引數(proj_id)必須是大於0的數,且這個數只有低8位起作用。

ftok通過計算指定檔案的索引節點的index和第2個引數proj_id,來建立乙個唯一的ipc key.

例如, /tmp/foo對應的檔案索引號是0x100000, 那麼proj_id等於42(0x2a), 那麼得到的key就是 0x2a100000

也就是說,對於不同的程序,只要ftok的2個引數相同,則得到的ipc key的值也會是相同的。

而對於同乙個ipc key, semget保證在不同的程序中能夠或得到相同的訊號量集合.

而這個訊號量集合是乙個核心資料結構,不會因為程序的退出而自動銷毀,所以需要程式顯式地進行銷毀。

semctl的man page

:

semctl( semid, 0, ipc_rmid, 0)

訊號量的使用主要是通過這2個函式,man page(

int semop(int semid, struct sembuf *sops, unsigned nsops); int semtimedop(int semid, struct sembuf *sops, unsigned nsops, struct timespec *timeout);

首先了解一下sembuf 的結構

struct sembuf ;

對於sem_op,分為下列幾種情況

struct sembuf sem[2]; // 第乙個操作 sem[0].sem_num = 0; // 操作訊號量集合中的第乙個訊號量 sem[0].sem_op = 0; // 保證此訊號量的值為0,否則阻塞 sem[0].sem_*** = sem_undo; // 如果操作過程中程序退出則回滾 // 第二個操作 sem[1].sem_num = 0; // 操作訊號量集合中的第乙個訊號量 sem[1].sem_op = 1; // 訊號量值增1,阻塞其它執行緒進入 sem[1].sem_*** = sem_undo; // 如果操作過程中程序退出則回滾 // 執行上述操作 if( semop( semid, sem, 2) == 0 )

這是一種很常見的情況,在生產者-消費者執行緒池模型中, 一組生產者執行緒從網路或者檔案中讀取到資料報並追加到工作任務佇列;另一組消費者執行緒從工作任務佇列中獲取工作任務後執行。

在這種模式下,這些消費者執行緒需要根據工作任務佇列中是否有需要處理的工作任務來及時地啟動或者等待執行。

首先對於生產者執行緒, 當將資料報追加到工作任務佇列後,可以將可用資源數增一,此操作永遠都不會阻塞

sem[0].sem_num = 0; // 指定操作的是該訊號量集合中的第乙個 sem[0].sem_op = 1; // 增1 sem[0].sem_*** = 0; semop( semid, sem, 1);

其次對於消費者執行緒

struct sembuf sem[1]; sem[0].sem_num = 0; // 操作訊號量集合中的第乙個訊號量 sem[0].sem_op = -1; // 如果佇列中有多餘乙個的工作任務,則理解返回,否則阻塞等待。 sem[0].sem_*** = sem_undo; // 如果操作過程中程序退出則回滾 // 執行上述操作 if( semop( semid, sem, 1) == 0 )

systemV訊號量 與 Posix訊號量

一 函式上的區別 訊號量有兩種實現 傳統的system v訊號量和新的posix訊號量。它們所提供的函式很容易被區分 對於所有system v訊號量函式,在它們的名字裡面沒有下劃線。例如,應該是semget 而不是sem get 然而,所有的的posix訊號量函式都有乙個下劃線。下面列出了它們提供的...

systemV訊號量的使用案例

systemv訊號量處理的函式有 semget semctl semop include intsemget key t key int nsems,int sem 說明 解釋功能 建立乙個新的訊號量或獲取乙個已經存在的訊號量的鍵值。返回值成功返回訊號量的標識碼id 失敗返回 1。引數 解釋 key...

System V 訊號量使用相關函式

在提到posix 訊號量時,指的是二值訊號量或計數訊號量,而system v訊號量指的是入了計數訊號量集 二值訊號量 其值為0或1,類似於互斥鎖,資源被鎖住時為0,資源可用為1 計數訊號量 其值在0和某個限制值之間的訊號量,訊號量的值就是可用資源數 計數訊號量集 乙個或多個訊號量構成乙個集合,集合中...