互斥鎖(Mutex)可用於同步資源訪問。
互斥(通常稱為Mutex)用於各種操作系統的資源管理。微控制器設備中的許多資源可以被重復使用,但一次只能被一個線程使用(例如通信通道、內存和文件)。互斥鎖用於保護對共享資源的訪問。創建一個互斥鎖,然后在線程之間傳遞(它們可以獲取和釋放互斥鎖)。
互斥鎖是信號量的特殊版本。像信號量一樣,互斥鎖也是一個令牌容器,但是有一個令牌,代表一個資源。因此,互斥鎖令牌是二值的且有邊界的。
互斥鎖的優點是它引入了線程所有權。當一個線程獲得一個互斥鎖並成為它的所有者時,后續從該線程獲取互斥鎖時將立即成功,沒有任何延遲(如果指定了osMutexRecursive屬性)。因此,互斥鎖的獲取/釋放可以嵌套。
Note:互斥鎖相關函數不能被中斷程序調用。
互斥鎖屬性:
osMutexAttr_t Data Fields | ||
---|---|---|
const char * | name | name of the mutex Pointer to a constant string with a human readable name (displayed during debugging) of the mutex object. Default: NULL no name specified. |
uint32_t | attr_bits | attribute bits The following bit masks can be used to set options:
Use logical 'OR' operation to select multiple options, for example: Default: 0 which specifies:
|
void * | cb_mem | memory for control block Pointer to a memory for the mutex control block object. Refer to Static Object Memory for more information. Default: NULL to use Automatic Dynamic Allocation for the mutex control block. |
uint32_t | cb_size | size of provided memory for control block The size (in bytes) of memory block passed with cb_mem. For RTX, the minimum value is defined with osRtxMutexCbSize (higher values are permitted). Default: 0 as the default is no memory provided with cb_mem. |
osMutexRecursive:互斥鎖嵌套屬性,同一個線程可以在不鎖定自身的情況下多次使用互斥鎖。每當擁有互斥鎖的線程獲得互斥鎖時,鎖計數就會增加。互斥鎖也必須被釋放多次,直到鎖定計數為零。當互斥量達到0時,互斥量實際上會被釋放,其他線程可以獲取互斥量。
osMutexPrioInherit:優先級繼承屬性,使用優先級繼承屬性的互斥鎖將 ”等待線程“ 的優先級轉移給當前互斥鎖的所有者(如果所有者的線程優先級較低)。這確保了低優先級線程不會阻塞高優先級線程。否則,低優先級線程可能持有互斥鎖,但由於另一個中優先級線程而沒有獲得執行時間。如果沒有優先級繼承,等待互斥鎖的高優先級線程將被中優先級線程阻塞,稱為優先級反轉。
osMutexRobust:互斥鎖健壯屬性,如果擁有的線程被終止(通過osThreadExit或osThreadTerminate),健壯的互斥鎖將被自動釋放。非健壯互斥鎖不會被釋放,用戶必須手動確保釋放互斥鎖。
osMutexId_t osMutexNew (const osMutexAttr_t *attr):
創建一個互斥鎖,attr是互斥鎖的屬性,返回執行互斥鎖ID或者NULL。
osStatus_t osMutexAcquire (osMutexId_t mutex_id, uint32_t timeout):
申請互斥鎖。timeout是等待互斥鎖的節拍數,0代表立即返回,不阻塞;osWaitForever代表一直等待,直到互斥鎖可用。
返回值:
osOK:獲取互斥鎖成功。
osErrorTimeout:等待超時失敗。
osErrorResource:當沒有指定超時時間時,獲得互斥鎖失敗。
osErrorParameter:mutex_id參數錯誤。
osErrorISR:中斷調用錯誤。
osStatus_t osMutexRelease (osMutexId_t mutex_id):
釋放互斥鎖。
返回值:
osOK:釋放互斥鎖成功。
osErrorResource:互斥鎖不能被釋放。當前進程沒有獲取互斥鎖或者不是互斥鎖的擁有者。
osErrorParameter:mutex_id參數錯誤。
osErrorISR:中斷調用錯誤。
1 osMutexId_t mutex; 2 const osMutexAttr_t mutex_attr = { 3 .name = "_ledThread mutex", 4 .attr_bits = osMutexRecursive | osMutexPrioInherit, 5 .cb_mem = NULL, 6 .cb_size = 0, 7 }; 8 9 static void _ledThread(void *argument); 10 11 void 12 test_mutex(void) 13 { 14 osThreadId_t thread; 15 16 mutex = osMutexNew(&mutex_attr); 17 18 osThreadNew(_ledThread, (void *)1, NULL); 19 osThreadNew(_ledThread, (void *)2, NULL); 20 } 21 22 static void 23 _ledThread(void *argument) 24 { 25 osStatus_t status; 26 uint32_t id = (uint32_t)argument; 27 uint32_t delay; 28 29 if(1 == id) { 30 delay = 500; 31 } else { 32 delay = 1000; 33 } 34 35 for(;;) { 36 status = osMutexAcquire(mutex, osWaitForever); 37 if(osOK == status) { 38 menuShow(&seg_led, delay, 0); 39 osDelay(delay); 40 osMutexRelease(mutex); 41 } 42 } 43 }