1. 信号量的简介
信号量是一种解决同步问题的机制,可以实现对共享资源的有序访问
- 当计数值大于0,代表有信号量资源
- 当释放信号量,信号量计数值(资源数)加一,直到溢出
- 当获取信号量,信号量计数值(资源数)减一,直到0
信号量:用于传递状态
2. 二值信号量
- 二值信号量实际上就只有空和满两种情况,所以称为二值。
- 二值信号量通常用于互斥访问或任务同步, 与互斥信号量比较类似,但是二值信号量有可能会导致优先级翻转的问题 ,所以二值信号量更适合用于同步。
2.1 二值信号量相关API函数
使用二值信号量的过程:创建二值信号量 ->释放二值信号量 -> 获取二值信号量
2.2 创建信号量函数
void OSSemCreate( OS_SEM * p_sem,
CPU_CHAR * p_name,
OS_SEM_CTR cnt,
OS_ERR * p_err )
2.3 释放信号量函数
OS_SEM_CTR OSSemPost( OS_SEM * p_sem,
OS_OPT opt,
OS_ERR * p_err)
2.4 获取信号量函数
OS_SEM_CTR OSSemPend( OS_SEM * p_sem,
OS_TICK timeout,
OS_OPT opt,
CPU_TS * p_ts,
OS_ERR * p_err )
3. 计数型信号量
计数型信号量与二值信号量是很相似的 ,但是计数型信号量的资源数大于1,也就是它的资源不止0和1。
计数型信号量适用场合:
注意:计数型信号量和二值信号量的API函数是公用的
4. 优先级翻转简介
- 优先级翻转:高优先级的任务反而慢执行,低优先级的任务反而优先执行
- 优先级翻转在抢占式内核中是非常常见的,但是在实时操作系统中是不允许出现优先级翻转的,因为优先级翻转会破坏任务的预期顺序,可能会导致未知的严重后果。
- 在使用二值信号量的时候,经常会遇到优先级翻转的问题。
- 高优先级任务被低优先级任务阻塞,导致高优先级任务迟迟得不到调度。但其他中等优先级的任务却能抢到CPU资源。从现象上看,就像是中优先级的任务比高优先级任务具有更高的优先权(即优先级翻转)
5. 互斥信号量
- 互斥信号量是一个拥有优先级继承的二值信号量,在同步的应用中二值信号量最适合。互斥信号量适合用于那些需要互斥访问的应用中。
- 优先级继承:当一个互斥信号量正在被一个低优先级的任务持有时, 如果此时有个高优先级的任务也尝试获取这个互斥信号量,那么这个高优先级的任务就会被阻塞。这个高优先级的任务会将低优先级任务的优先级提升到与自己相同的优先级。
优先级继承并不能完全的消除优先级翻转的问题,它只是尽可能的降低优先级翻转带来的影响
注意:互斥信号量不能用于中断服务函数中,原因如下:
- 互斥信号量有任务优先级继承的机制, 但是中断不是任务,没有任务优先级, 所以互斥信号量只能用于任务中,不能用于中断服务函数。
- 中断服务函数中不能因为要等待互斥信号量而设置阻塞时间进入阻塞态。
5.1 互斥信号量相关API函数
使用流程:创建互斥信号量 -> 获取信号量 ->释放信号量
注意:创建互斥信号量时,默认信号量有效
5.2 创建互斥信号量函数
void OSMutexCreate ( OS_MUTEX* p_mutex,
CPU_CHAR * p_name,
OS_ERR * p_err )
5.3 获取互斥信号量
void OSMutexPend ( OS_MUTEX* p_mutex,
OS_TICK timeout,
OS_OPT opt,
CPU_TS * p_ts,
OS_ERR * p_err )
5.4 释放互斥信号量
Void OSMutexPost ( OS_MUTEX* p_mutex,
OS_OPT opt,
OS_ERR * p_err)
评论区