(1)定义并初始化互斥体:
struct mutex my_mutex;
mutex_init()&my_mutex;
(2)获取互斥体:
void mutex_lock(struct mutex *lock); // 不可中断
int mutex_lock_interruptible(struct mutex *lock); // 可中断
int mutex_trylock(struct mutex *lock);
(3)释放互斥体:
void mutex_unlock(struct mutex *lock);
mutex的使用方法和信号量用于互斥的场合完全一样:
struct mutex my_mutex; /* 定义mutex */
mutex_init(&my_mutex); /* 初始化mutex */
mutex_lock(&my_mutex); /* 获取mutex */
... /* 临界资源 */
mutex_unlock(&my_mutex); /* 释放mutex */
总结:
互斥体是进程级的,用于多个进程之间对资源的互斥。当资源竞争失败时,会发生进程上下文切换,当前进程进入睡眠状态,CPU将运行其它进程。鉴于上下文切换的开销也很大,因此:
- 只有当进程占用资源时间较长时,用互斥体才是较好的选择。
- 当要保护的临界区访问时间较短时,用自旋锁更方便
自旋锁和互斥体选用的3项原则:
- 当锁不能被获取到时,使用互斥体的开销是进程上下文切换时间,使用自旋锁的开销是等待获取自旋锁(由临界区执行时间决定)。若临界区比较小,宜使用自旋锁,若临界区很大,应使用互斥体。
- 互斥体所保护的临界区可包含可能引起阻塞的代码,而自旋锁则绝对要避免用来保护包含这样代码的临界区。因为阻塞意味着要进行进程的切换,如果进程被切换出去后,另一个进程企图获取本自旋锁,死锁就会发生。
- 互斥体存在于进程上下文,因此,如果被保护的共享资源需要在中断或软中断情况下使用,则在互斥体和自旋锁之间只能选择自旋锁。当然,如果一定要使用互斥体,则只能通过mutex_trylock()方式进行,不能获取就立即返回以避免阻塞。