各位看官們,大家好,上一回中咱們說的是使用信號量進行進程間同步與互斥的例子,這一回咱們繼續說該例子。閒話休提,言歸正轉。讓我們一起talk C栗子吧!
我們在上一回中介紹了如何使用信號量進行進程間同步與互斥,不過介紹的都是理論,這一回我們要通過具體的實踐來介紹如何使用信號量進行進程間同步與互斥。光說不練,不是我們的作風,哈哈。
我們使用的Linux系統提供了信號量機制,並且提供了相應的API來操作信號量。信號量類似我們在前面章回中介紹的共享內存和消息隊列,它也是System V IPC中的一部分,操作信號量的方法和操作共享內存以及消息隊列的方法十分類似,接下來我們介紹與信號量相關的函數。
int semget(key_t key,int num_sems, int sem_flag)
該函數用來創建一個新的信號量或者獲取已經存在的信號量。
第一個參數是鍵值,通過它來操作IPC在內核中的結構,也就是信號量在內核中的結構;(前面章回中介紹過) 第二個參數是信號量的數目,通常為1;第三個參數表示操作信號量的權限,該權限和文件權限一樣;該函數運行成功時返回信號量的標識符,否則返回-1;我們可以通過該標識符使用信號量;
int semop(int sem_id, struct sembuf *sem_ops,size_t sem_ops_num)
該函數用來修改信號量的值,也就是對信號量的P/V操作;
第一個參數是信號量的標識符,通過semget函數可以獲得;第二個參數是一個指針,該指針指向結構體類型的變量,該變量中包含中對信號的操作內容和操作方式;第三個參數表示信號量操作的數量,也就是第二個參數的數量,通常為1;該函數運行成功時返回0,否則返回-1;函數的第二個參數的類型是一個結構體,該結構體的定義如下:
struct sembuf
{
unsigned short sem_num; /* semaphore number */
short sem_op; /* semaphore operation */
short sem_flg; /* operation flags */
}
我們詳細介紹一下該結構體的成員:
第一個成員表示信號量的編號,通常為0,表示單個信號量,如果非0,則表示一組信號量;第二個成員表示對信號量操作的數值,通常為1或者-1,也就是對信號量加1或者減1(對應V/P操作);第三個成員表示對信號量的操作方式,通常為SEM_UNDO,表示讓系統對信號量進行跟蹤處理;該函數代表的動作是一個原子操作,使用它的時候,不用擔心是否會被其它操作中斷。
int semctl(int sem_id, int sem_num, int cmd, ...)
該函數用來控制信號量,通常用來初始化或者刪除信號量;
第一個參數是信號量的標識符,通過semget函數可以獲得;第二個參數是信號量的編號,通常為0,表示單個信號量,如果非0,則表示一組信號量;第三個參數是一個命令,該命令有許多個,常用的是SETVAL和IPC_RMID,表示初始化和刪除信號量;該函數是可變參數的函數,可能還有其它類型的參數; 該函數運行成功時返回0,否則返回-1;我們在使用該函數的時候通常都需要第四個參數,該參數為一個聯合體類型,詳細的定義如下所示:
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) */
};
如果系統中沒有定義該類型的話,我們需要定義該類型。
如果第三個參數賦值為SETVAL時,表示初始化信號量,我們需要第四個參數,並且使用semun中val值去初始化信號量。如果第三個參數賦值為IPC_RMID,表示刪除信號量,那麼不需要第四個參數。各位看官,關於使使用信號量進行進程間同步與互斥的例子咱們就說到這裡。欲知後面還有什麼例子,且聽下回分解 。