VxWorks主要提供如下API進行信號量的創建、獲取和釋放:
參數1:SEM_Q_PRIORITY,SEM_Q_FIFO
SEM_Q_PRIORITY(值為0x1):需要獲取該信號量的任務基於優先級順序排列。
SEM_Q_FIFO(值為0x0):需要獲取該信號量的任務基於等待任務隊列的先進先出順序排列。
參數2: SEM_FULL,SEM_EMPTY
SEM_Q_FIFO(值為0x0):需要獲取該信號量的任務基於等待任務隊列的先進先出順序排列。
參數2: SEM_FULL,SEM_EMPTY
SEM_FULL: 初始化信號量為滿(可用),
SEM_EMPTY: 后者初始化信號量為空(不可用)。
(1)semBCreate( ):分配並初始化一個二進制信號量,函數原型為:
SEM_ID semBCreate
(
int options, /*信號量選項*/
SEM_B_STATE initialState /*信號量初始化狀態值*/
) ;
(2)semMCreate( ):分配並初始化一個互斥信號量,函數原型為:
SEM_ID semBCreate
(
int options, /*信號量選項*/
SEM_B_STATE initialState /*信號量初始化狀態值*/
);
(3)semCCreate( ):分配並初始化一個計數信號量,函數原型為:
SEM_ID semCCreate
(
int options, /*信號量選項*/
int initialCount /*信號量初始計數值*/
) ;
當一個信號量被創建時,它的隊列(queue)類型需要被確定。等待信號量的任務隊列可以以優先級順序 (SEM_Q_PRIORITY)或者先到先得方式(SEM_Q_FIFO)排列。
SEM_ID semBCreate
(
int options, /*信號量選項*/
SEM_B_STATE initialState /*信號量初始化狀態值*/
) ;
(2)semMCreate( ):分配並初始化一個互斥信號量,函數原型為:
SEM_ID semBCreate
(
int options, /*信號量選項*/
SEM_B_STATE initialState /*信號量初始化狀態值*/
);
(3)semCCreate( ):分配並初始化一個計數信號量,函數原型為:
SEM_ID semCCreate
(
int options, /*信號量選項*/
int initialCount /*信號量初始計數值*/
) ;
當一個信號量被創建時,它的隊列(queue)類型需要被確定。等待信號量的任務隊列可以以優先級順序 (SEM_Q_PRIORITY)或者先到先得方式(SEM_Q_FIFO)排列。
(4)semDelete( ):刪除一個自由的信號量,函數原型為:
STATUS semDelete
(
SEM_ID semId /*要刪除的信號量ID號*/
);
(5)semTake( ):占有一個信號量,函數原型為:
STATUS semTake
(
SEM_ID semId /*所要得到的信號量ID號*/
int timeout /*等待時間*/
);
(6)semGive( ):釋放一個信號量,函數原型為:
STATUS semGive
(
SEM_ID semId /*所給出的信號量ID號*/
);
(7)semFlush( ):解鎖所有等待信號量的任務,函數原型為:
STATUS semFlush
(
SEM_ID semId /*要解鎖的信號量ID號*/
);
二進制信號量:
要創建一個發揮互斥作用的二進制信號量一般使用semBCreat(xxx, SEM_FULL)調用,其中的SEM_FULL暗示該信號量用於任務間的互斥(最開始二進制信號量可獲得)。對臨界區域(critical region)的訪問需以semTake和semGive加以保護:
semTake (semMutex, WAIT_FOREVER);
. . /*critical region, only accessible by a single task at a time*/
semGive (semMutex);
semTake (semMutex, WAIT_FOREVER);
. . /*critical region, only accessible by a single task at a time*/
semGive (semMutex);
要創建一個發揮同步作用的二進制信號量一般使用semBCreat(xxx, SEM_EMPTY) 調用,其中的SEM_EMPTY 暗示該信號量用於任務間的同步(即最開始二進制信號量不可獲得)。
二進制信號量使用最廣泛的一種情況是中斷與任務間通信。中斷服務程序一般以二進制信號量“通知”對應的任務進行中斷后的處理工作,例如:
SEM_ID syncSem;/* ID of sync semaphore */
myTask(void)
{
semTake(syncSem, WAIT_FOREVER); /* wait for event to occur */
printf("my Task got the semaphore/n");
... /* process event */
}
二進制信號量使用最廣泛的一種情況是中斷與任務間通信。中斷服務程序一般以二進制信號量“通知”對應的任務進行中斷后的處理工作,例如:
SEM_ID syncSem;/* ID of sync semaphore */
myTask(void)
{
semTake(syncSem, WAIT_FOREVER); /* wait for event to occur */
printf("my Task got the semaphore/n");
... /* process event */
}
eventInterruptSvcRout(void)
{
semGive(syncSem); /* let my Task process event */
...
}
{
semGive(syncSem); /* let my Task process event */
...
}
互斥信號量
互斥信號量可以看作一種特殊的二進制信號量,其支持普通二進制信號量不支持的一些特性,提供優先級繼承、安全刪除和回歸能力。互斥信號量的使用方法和二進制信號量基本類似,但有如下區別:
(1)僅僅被用做互斥,不能提供同步機制;
(2)只能被使用它的任務釋放;
(3)中斷服務程序(ISR)不能釋放它;
(4)不能使用函數semFlush( );
(5)支持使用二進制信號量進行互斥時所不支持的優先級“翻轉”。
(1)僅僅被用做互斥,不能提供同步機制;
(2)只能被使用它的任務釋放;
(3)中斷服務程序(ISR)不能釋放它;
(4)不能使用函數semFlush( );
(5)支持使用二進制信號量進行互斥時所不支持的優先級“翻轉”。
任務的優先級翻轉是指高優先級任務因等待低優先級任務占用的互斥資源而被較低優先級(高於低優先級但低於高優先級)的任務不斷搶占的情況。VxWorks操作系統提供優先級繼承機制對優先級翻轉進行預防。占用互斥資源但優先級較低的任務被暫時地提高到等待該資源的最高優先級任務的優先級。這樣,中等優先級的任務將無法搶占原本低優先級的任務,使得低優先級任務能盡快執行,釋放出優先級較高的任務所需要的資源。
為了使互斥信號量支持優先級繼承支持,我們在調用semMCreate時應使用SEM_Q_PRIORITY和SEM_INVERSION_SAFE選項。互斥信號量提供互斥也需要對臨界區域進行保護:
為了使互斥信號量支持優先級繼承支持,我們在調用semMCreate時應使用SEM_Q_PRIORITY和SEM_INVERSION_SAFE選項。互斥信號量提供互斥也需要對臨界區域進行保護:
semTake (semMutex, WAIT_FOREVER);
. . //critical region, only accessible by a single task at a time .
semGive (semMutex);
. . //critical region, only accessible by a single task at a time .
semGive (semMutex);
計數信號量
計數信號量是任務同步和互斥的另一種實現方式.計數信號量除了保留信號量被釋放的次數以外和二進制信號量是一樣的。每次信號量被釋放(gaven)一次,計數增加;每次信號量被占用(taken)一次,計數減少;當計數減少為0時,要求得到信號量的任務被阻塞(blocked)。二進制信號量是如果一個信號量被釋放,有一個任務阻塞等待,則這個任務就被unblock.而計數信號量如果一個信號量被釋放,沒有任務阻塞等待,則計數增加。這說明一個被釋放兩次的計數信號量可以被占用(taken)兩次,沒有阻塞
互斥型信號量必須是同一個任務申請,同一個任務釋放,其他任務釋放無效。同一個任務能遞歸申請。
二進制信號量,一個任務申請成功后,能由另一個任務釋放。可用於任務同步,也可用於互斥
計數信號量可用於隊列數據的存儲