概述
多任务系统中存在一种潜在的风险,当一个任务在使用某个资源的过程中,即还没有完全结束对资源的访问时,便被切出运行态,使得资源处于非一致,不完整的状态,如果这个时候有另一个任务或者中断来访问这个资源,则会导致数据损坏或者其他相似的错误。
会发生该问题的情景:
- 对外设的操作
- 读-改-写操作
- 变量的非原子访问
- 函数重入
一个函数只访问自己栈空间上的数据或者是内核寄存器中的数据,不访问其他任何数据,比如全局变量啥的,则这个函数就是重入的。否则不可重入。
互斥
互斥保证资源在被访问后具有排他性,防止资源被意外修改
最高的互斥方法
尽量不要共享资源,或者是每个资源都通过单任务访问。
互斥的方法
临界区与挂起调度器
- 基本临界区
临界区指在访问资源前,关闭全部中断,在访问资源后,再恢复中断,是一种非常原始的方法。
临界区必须只具有很短的时间,否则会反过来影响中断响应时间
- 挂起(锁定)调度器
挂起调度器,保证代码区不会被其他任务或中断打断。
互斥量
互斥量是一种特殊的二值信号量,用于控制在两个或多个任务间访问共享数据。
互斥量的机制:
一个任务想要合法地访问资源,必须先成功的得到该资源对应的令牌,当完成对资源的使用后,必须马上归还令牌。只有归还了令牌,其他任务才可能访问共享资源。
互斥量和二值信号量的区别:
- 用于互斥的信号量必须归还
- 用于同步的信号量通常是完成同步后便丢弃,不再归还
优先级反转
互斥量容易导致一个问题是优先级反转,优先级反转会导致重大问题
即高优先级任务因为无法获取互斥信号,而阻塞,导致低优先级优先运行。
更严重的一种情形:
低优先级先运行,获得互斥量,高优先级无法获得互斥量而阻塞,这时候,一个中等优先级任务开始运行,抢占了低优先级,然后低优先级任务block了,无法give互斥量,从而高优先级也无法运行。
优先级继承
最小化减少优先级反转的负面影响,但不能完全消除。
通过暂时的将互斥量持有者的优先级提升至所有等待此互斥量的任务所具有的最高优先级,互斥量持有者归还互斥量后,优先级会自动设置为其原来的优先级。
死锁
两个资源都等待被对方持有时,两个任务都无法再继续执行,这种情况成为死锁。
守护程序
守护程序提供一种干净利落的方法来实现互斥功能,而不用担心会发生优先级反转和死锁。
守护任务是对某个资源具有唯一所有权的任务,只有守护任务才可以直接访问其守护的资源,其他任务要访问该资源只能简介的通过守护任务提供的服务。
守护程序的实现机制:
利用队列,当其他任务想使用某个资源的时候,通过队列发送消息给守护程序,由守护程序对资源进行操作。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。