一: 互斥型信號量的理解
互斥型信號量首先是二值信號量,實現對共享資源的獨佔式處理,其次互斥型信號量可以在應用程序代碼中用於降解優先級的反轉問題,這個是它和普通信號量的最本質的區別。
二: 優先級反轉的問題
假設現在有三個任務分別是Task1,Task2,Task3,優先級從大到小。程序在運行過程中,Task1和Task2處於掛起(pend)的狀態,等待某個事件的發生。這樣優先級最低的Task3首先申請到了mutex並開始同共享資源打交道,過了一會兒,Task1等待的事件出現了,那麼此時Task1就需要使用共享資源了,於是申請mutex(OSMutexPend)。在這種情況下,OSMutexPend注意到高優先級的任務要使用這個共享資源,於是將Task3的優先級升到比Task1更高的級別,並強制任務調度回到Task3。而Task1只好繼續掛起,等待共享資源被釋放。同時Task3繼續運行,直到Task3調用OSMutexPost(),釋放Mutex.在調用OSMutexPost()時,OSMutexPost()會將Task3的優先級恢復到原來的水平,同時還會注意到有個高優先級的任務Task1需要這個Mutex,於是將這個Mutex交給Task1,並做任務切換。
三:uc/os-ii的互斥型信號量由三個部分組成:
◆一個標誌,指示mutex是否可以使用(0或1)
◆一個優先級,準備一旦高優先級的任務需要這個mutex,賦予給佔有mutex的任務。
◆一個等待該mutex的任務列表
四:程序示例:
Void main (void)
{
OSInit();
**************應用程序初始化**********************
OSMutexCreate(9,&err);
OSTaskCreate(TaskPrio10,(void *)0,&TaskPrio10Stk[999],10);
OSTaskCreate(TaskPrio15,(void *)0,&TaskPrio15Stk[999],15);
OSTaskCreate(TaskPrio20,(void *)0,&TaskPrio20Stk[999],20);
**************應用程序初始化************************
OSStart();
}
Void TaskPrio10 (void * pdata)
{
While(1){
*************應用程序代碼***********************
OSMutexPend(ResouceMutex,0,&err);
*************佔用共享資源***********************
OSMutexPost(ResouceMutex);
*************應用程序代碼***********************
}
}
Void TaskPrio15 (void * pdata)
{
While(1){
*************應用程序代碼***********************
OSMutexPend(ResouceMutex,0,&err);
*************佔用共享資源***********************
OSMutexPost(ResouceMutex);
*************應用程序代碼***********************
}
}
Void TaskPrio20 (void * pdata)
{
While(1){
*************應用程序代碼***********************
OSMutexPend(ResouceMutex,0,&err);
*************佔用共享資源***********************
OSMutexPost(ResouceMutex);
*************應用程序代碼***********************
}
}
五,三個重要函數的應用
1. OSMutexCreate (INT8U prio, INT8U *err)
Arguments : prio is the priority to use when accessing the mutual exclusion semaphore. In other words, when the semaphore is acquired and a higher priority task attempts to obtain the semaphore then the priority of the task owning the semaphore is raised to this priority. It is assumed that you will specify a priority that is LOWER in value than ANY of the tasks competing for the mutex.
err is a pointer to an error code which will be returned to your application:
OS_NO_ERR if the call was successful.
OS_ERR_CREATE_ISR if you attempted to create a MUTEX from an ISR
OS_PRIO_EXIST if a task at the priority inheritance priority already exist.
OS_ERR_PEVENT_NULL No more event control blocks available.
OS_PRIO_INVALID if the priority you specify is higher that the maximum allowed (i.e. > OS_LOWEST_PRIO)
Returns : != (void *)0 is a pointer to the event control clock (OS_EVENT) associated with the created mutex.
== (void *)0 if an error is detected.
2. OSMutexPend (OS_EVENT *pevent, INT16U timeout, INT8U *err)
Arguments : pevent is a pointer to the event control block associated with the desired mutex.
Returns : none
2. OSMutexPost (OS_EVENT *pevent)
Arguments : pevent is a pointer to the event control block associated with the desired mutex.