第5章 Posix信號量
5.1 概述
Posix信號量分爲兩種:
1. 有名信號量:使用Posix IPC名字標識。
2. 內存信號量:存放在共享內存區中。
Posix信號量不必在內核中維護(System V信號量由內核維護),由可能爲路徑名的名字來標識。
5.2 基本操作
三種基本操作:
1. 創建(create):指定初始值。
2. 等待(wait):如果值小於等於0則阻塞,否則將其減一,又稱P操作。
3. 掛出(post):將信號量的值加1,加後如果值大於0,則喚醒一個阻塞在等待上的線程,又稱V操作。
二值信號量可用於互斥,就像互斥鎖一樣。但互斥鎖必須由鎖住它的線程解鎖,信號量的掛出卻不必由執行過等待的同一線程執行。
信號量的wait和post與條件變量的wait和signal類似,區別是:因爲永久的改變了信號量的值,信號量的操作總被記住(會影響到後續的操作);條件變量的signal如果沒有線程在等待,該信號將丟失(對後續操作沒有影響)。
互斥鎖是爲上鎖而優化的,條件變量是爲等待優化的,信號量既可以上鎖也可以等待,因此開銷更大。
5.3 Posix信號量操作
有名信號量: |
內存信號量: |
sem_open |
sem_init:需要指定是否共享 |
sem_wait:原子的“測試並減1”操作 |
|
sem_trywait |
|
sem_post:同步技巧中唯一能在信號處理函數內安全調用的操作 |
|
sem_getvalue |
|
sem_close |
sem_destroy |
sem_unlink |
|
即使當前沒有進程打開信號量,它的值仍然保持,因此Posix有名信號量至少是隨內核持續的。
在父進程中打開的任何信號量,fork後在子進程中仍打開。
5.4 生產者-消費者問題
這裏的解決方案需要一個二值信號量、兩個計數信號量:
1. mutex:二值信號量用於提供buffer的互斥訪問。
2. nempty:初始爲n的信號量,空槽位數。
3. nstored:初始爲0,已填寫的槽位數。
Posix允許sem_wait檢測死鎖並返回EDEADLK錯誤,但很多實現都沒有提供這一功能。
多個緩衝區問題是生產者-消費者問題的變種。
5.5 內存信號量
彼此無親緣關係的進程間需使用信號量時,一般用有名信號量。如果不需要使用關聯名字時,可改用內存信號量。
內存信號量需要放在共享內存區中,並由sem_init函數初始化爲shared狀態才能被不同進程使用,這種情況下它的持續性與共享內存區相同。
5.6 信號量限制
兩個限制:
1. SEM_NSEMS_MAX:一個進程可同時打開着的最大信號量數。
2. SEM_VALUE_MAX:一個信號量的最大值。