---- 整理自狄泰软件唐佐林老师课程
文章目录
- 1. 问题一
- 1.1 当前实现的深入分析
- 1.2 解决方案设计
- 1.3 解决方案实现步骤
- 1.4 编程实验:EnterCritical()重设计
- 2. 问题二
- 2.1 互斥锁的优化设计
- 2.2 互斥锁的优化实现方案
- 2.3 编程实验:互斥锁的优化实现
- 3. 小结
1. 问题一
- 在当前任务实现下,阻塞的多个任务重新进入执行态,会发生什么?
1.1 当前实现的深入分析
1.2 解决方案设计
- 任务从阻塞中(因获取锁失败而阻塞)恢复执行时
- 必须再次尝试获取锁 ==>
- 任务怎么知道锁是否获取成功?
- 内核需要 返回获取锁的 结果 给任务(成功 or 失败)
- 成功:任务继续执行,进入临界区
- 失败:任务 等待机会 再次尝试获取锁
1.3 解决方案实现步骤
- 在系统调用EnterCritical()中向内核传入 标记变量wait的地址
- 内核根据目标Mutex的状态(空闲or占用)设置标记变量wait的值
- 任务从系统调用返回后,判断并标记变量wait的值
- true:再次尝试获取锁
- false:无需再次尝试,继续向下执行
1.4 编程实验:EnterCritical()重设计
- 问题演示:【参看链接】:65 - 进程互斥锁的优化实现 / 00问题演示
- 优化:【参看链接】:65 - 进程互斥锁的优化实现 / 01优化
2. 问题二
- 如果有任务比较聪明,在进入临界区之前,先主动调用ExitCritical(),会发生什么?
- 任务不使用临界资源,但是要销毁已经存在的互斥锁,行为合法吗?
2.1 互斥锁的优化设计
- 同一个任务中可多次获取同一个互斥锁
- 同一个任务中多次调用EnterCritical()不会阻塞
- 只有获取锁的任务,才能释放锁
- 强行释放锁(异常行为) 的任务将被内核直接杀死
- 无法销毁处于占用状态的互斥锁
- 强行调用DestroyMutex()销毁占用状态的锁,将 无效返回
2.2 互斥锁的优化实现方案
-
任务通过自身标识对锁进行标记
mutex->lock = (uint)gCTaskAddr
-
释放锁时,通过锁标记与任务自身标识判断合法性
IsEqual(mutex->lock, gCTaskAddr)
-
只有未标识的锁能被销毁
IsEqual(mutex->lock, 0)
==> true
2.3 编程实验:互斥锁的优化实现
【参看链接】:65 - 进程互斥锁的优化实现 / 01优化
- 问题验证:
- 同一个任务中可多次获取同一个互斥锁
- 同一个任务中多次调用EnterCritical()不会阻塞
- 无法销毁处于占用状态的互斥锁
- 强行调用DestroyMutex()销毁占用状态的锁,将无效返回
- 只有获取锁的任务,才能释放锁
- 强行释放锁(异常行为)的任务将被内核直接杀死
3. 小结
- 互斥锁是一种特殊的内核变量,用于保护临界资源
- 多个任务在互斥锁的协调下,能够有序互斥的执行
- 互斥锁的具体实现需要在内核中完成
- 互斥锁的使用需要遵循预定的规则