互斥锁(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: osMutexRecursive | osMutexPrioInherit;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 }