信號量是一種用於提供不一樣進程或統一進程間不一樣線程同步手段的原語,其操做包括P操做(將信號量的值-1)和V操做(將信號量值+1),其典型應用場景爲多個生成者和多個消費者的狀況,也用於控制多個進程的併發數。POSIX信號量包含兩種類型:安全
a) POSIX有名信號量:使用PosixIPC名字標識併發
相關函數:函數
頭文件 #include<semaphore.h>post
建立:sem_t*sem_open(const char *name, into flag, /mode_t mode, unsigned int value */);優化
成功返回指向信號量的指針,若出錯則爲SEM_FAILED(注意不爲-1);value用於指定信號量的初始值,但該值不超過SEM_VALUE_MAX ;其他用法同mq_open線程
關閉:int sem_close(sem_t*sem); //成功返回0,若出錯則爲-1指針
關閉一個信號量並無將它從系統中刪除,即POSIX有名信號量至少具備隨內核的持續性,即便當前沒有進程打開着某個信號量,它的值仍然保持。進程
刪除:int sem_unlink(constchar *name); //若成功則爲0,若出錯則爲-1內存
等待(P操做):int sem_wait(sem_t *sem); //阻塞形式,成功返回0,失敗爲-1;若被信號中斷,錯誤碼爲EINTRget
intsem_trywait(sem_t *sem); //非阻塞形式,成功返回0,失敗爲-1;當沒法當即獲取信號量時返回EAGAIN錯誤
掛出(V操做):int sem_post(sem_t *sem); //成功返回0,失敗-1
取值:intsem_getvalue(sem_t *sem, int *valp); //成功返回0,失敗-1;成功則信號量的值存放與valp指向的變量中,若該信號量當前已上鎖,則*valp爲0或者負數,負數表示等待該信號量解鎖的進程數爲-*valp。有些平臺上的實現是信號量*valp不會爲負值。
p.s:在內核中,建立信號量的默認路徑是/dev/shm,因此以/tmp/semname建立信號量會出錯,解決辦法是以semname做爲參數建立信號量,將建立/dev/shm/sem.semname文件
b) POSIX基於內存的信號量:存放在內存中或共享內存中(存放在非共享內存中的只能用於線程同步)
相關函數:
建立和初始化信號量:intsem_init(sem_t *sem, int shared, unsigned int value);
sem參數執行應用程序必須分配的sem_t變量,若是shared 爲0,那麼待初始化的信號量是同一進程間各線程共享的,不然該信號量是在進程間共享的。當shared爲非零時,該信號量必須存在某種類型的共享內存中,而要使用它的各個進程都須要能訪問該共享內存。
返回值:失敗返回-1,成功返回0
摧毀信號量:int sem_destroy(sem_t*sem); //失敗返回-1,成功返回0
有名信號量和無名信號量二者的幾點區別:
一、 有名信號量具備隨內核的持續性,而無名信號量至少具備隨進程的持續性,然而其真正的持續性卻取決於存放信號量的內存區的類型,只有含有某個基於內存信號量的內存區保持有效,該信號量就一直存在。
二、 因爲上述的區別也致使了刪除有名信號量用sem_unlink(相似刪除文件unlink),摧毀無名信號量用sem_destroy(有點至關於sem_close+sem_unlink;若不調用則隨進程或共享內存區結束)
三、 其他的掛出、等待和取值操做一致
最後,總結一下信號量與互斥量,條件變量的差別:
1) 互斥鎖老是由給它上鎖的線程解鎖,信號量的掛出卻沒必要由執行過它的等待操做的同一線程執行
2) 互斥鎖要麼被鎖住,要麼被解開(相似於二值信號量)
3) 信號量的掛出(post——+1)操做老是被記住,反映在信號量的值上;然而當向一個條件變量發送信號時,若是沒有線程等待在該條件變量上,那麼信號將丟失
4) 互斥量和條件變量多用於線程同步,但也可用於進程間;信號量的意圖在於進程間同步,但也可用於線程間。
5) 在各類同步技巧中(互斥量+條件變量、讀寫鎖、信號量),可以從信號處理程序中安全調用的惟一函數是sem_post
6) 互斥鎖是爲上鎖而優化的,條件變量是爲等待而優化的,信號量既可用於上鎖也可用於等待,於是可能致使更多的開銷和更高的複雜性;使用時結合實際