目录
本学笔记基于zephyr 工程版本 2.2.99,主机环境为ubuntu18.04,开发平台 nrf52840dk_nrf52840
摘要
互斥锁(mutexes )一般用于资源访问的互斥,简单的互斥通过信号量去做也可以,但是在基于优先级调度的实时系统使用信号量做资源保护,容易引发优先级翻转的的问题,而互斥锁会动态的调整调用线程的优先级,从而避免了优先级翻转的问题。
1 概念
任意数量的互斥锁可以被定义,引用互斥锁时使用的是内存地址,所以可以随便定义。
互斥锁有以下关键属性:
lock count, 代表了在线程中被上锁的次数,如果这个数为0,代表已经是非锁定状态。
owning thread, 代表了哪个线程给这个互斥锁上锁。
当有多个线程,访问同一个公共资源时(比如读写全局变量),为了实现互斥访问,可以定义一个互斥锁来保护这个资源,当访问资源时,需要首先获取互斥锁。当这个互斥锁被其他线程上锁后,当前访问这个互斥锁的线程可以选择等待这个互斥锁被解锁。任意数量的线程可以同时等待给互斥锁上锁, 当互斥锁可用时,优先级最高等待时间最长的线程可以优先访问。因为访问的是公共资源,所以上锁后,需要尽量短的时间使用这个资源。否则,长时间被上锁后,其他线程也需要等待相同的时间。上锁和解锁一般是成对出现的,尽量不要嵌套,否则会引起死锁,死锁的问题是很不好排查的。
2 实现
2.1 定义互斥锁
使用struct k_mutex类型定义一个互斥锁变量。互斥锁必须在使用之前通过k_mutex_init()进行初始化。
下面的代码定义并初始化互斥锁:
struct k_mutex my_mutex;
k_mutex_init(&my_mutex);
同样,也可以使用K_MUTEX_DEFINE宏,在编译时定义和初始化互斥锁。
K_MUTEX_DEFINE(my_mutex);
2.2 上锁
调用k_mutex_lock()给一个互斥锁上锁。
下面的代码表示给一个互斥锁上锁,K_FOREVER表示当锁被其他线程锁定时,当前线程一直睡眠,知道互斥锁变为可用:
k_mutex_lock(&my_mutex, K_FOREVER);
也可以不一值等待,仅等待一段时间,下面代码表示锁不可用时等待100ms:
if (k_mutex_lock(&my_mutex, K_MSEC(100)) == 0) {
/* mutex successfully locked */
} else {
printf("Cannot lock XYZ display\n");
}
2.3 解锁
调用k_mutex_unlock()解锁互斥锁,
k_mutex_unlock(&my_mutex);
3 参考链接
https://docs.zephyrproject.org/latest/reference/kernel/synchronization/mutexes.html#id2