CC2640开发记录4 TI-RTOS 信号量 Semaphore

信号量是TI-RTOS中管理任务的重要组件,必须认真研究。

》信号量是最原始的基本的阻塞任务的组件

- 信号量记录了一个count,这个count>=0

- posting信号量操作会增加这个计数值

- pending一个计数值会减少这个计数值

-如上图所示

定义了一个名叫mySem的信号量,初始值为0 ,POST操作使得信号量++, PENDING操作使得信号量--如果是计数信号量,POST操作持续++ ,如果只是二进制的信号量,POST操作最多使得其为1。图片解释很明确。

如果在MYTASK任务中写入了Pend(mySem)语句,那么TASK运行到PEND语句后,就会进入BLOCKED状态。

换句话说,如果TASK中包含了PEND信号量,且信号量值为0,那么TASK将会BLOCK

 

当TASK PENDING 一个非0的信号量,那么会--此信号量,直至其减为0,变为BLOCKED状态,也就是TASK会运行信号量值大小的次数。

 

在正在运行的低优先级TASK里,POST了一个高优先级TASK一直PENDING的信号量,此时低优先级TASK会进入BLOCK状态,从而转入高优先级任务中去。

 多个TASK 共享一个信号量的情况。

高优先级 中等优先级 低优先级 三个等级的任务共享了一个信号量mySem,低优先级在运行状态时POST共享的信号量,此时低优先级的任务进入block状态,高优先级开始运行,运行结束后,mySem信号量变0,中等优先级任务不会再运行了,也就是说只有一次运行机会,给到了高优先级任务,中等优先级没有机会被运行。

二进制信号量的用法示例

首先定义了两个任务,一个高优先级,一个低优先级,注意这两个任务共享了一个名叫resource的内存,如果两个TASK同时访问了resource内存,就好像十字路口两个车撞上了一样,是不允许的,信号量就是红绿灯,避免此问题发生。

这两个TASK在死循环中都pend了mySem信号量,也就是说,这两个TASK都是处于BLOCK状态的,这里官方文档指明,mySem变量的初始化值是1,于是咱们继续往下思考。

mySem的值=1,此时高优先级的TASK会被运行,也就是高优先级与低优先级同样都在pend信号量,信号量=1信息来了,好处先让高优先级占了,高优先级TASK运行,做了resource++操作,之后,高优先级的TASK又post了mysem信号量,注意看下面的语句Task_sleep(4);这里指的是TASK休眠一段时间,否则永远都不会有机会让低优先级的TASK运行,因为调度器的原则始终是高优先级的优先。因为有了SLEEP,于是低优先级的TASK得以运行,低优先级PEND的信号量在高优先级中被POST了,所以低优先级里的resource也被++了;这两个TASK都被运行到了。

实例讲的很清楚,如何使用二进制信号量控制两个有优先级差别的TASK共享数据。

计数信号量可以控制TASK访问一组多个资源

这里介绍了一个餐馆算法

TASK扮演顾客,桌子上的饭菜代表了资源,服务员代表了信号量

信号量的初始值代表了有饭菜的桌子数量

顾客坐上了有饭菜的桌子,也就是TASK里面pending了信号量,前文说了,pending信号量会使得信号量--,如果信号量为0了,说明桌子坐满了,资源用完了,没有坐下来的顾客(TASK)就只能等了(进入BLOCK态)。

如果顾客吃完了,资源访问结束了,那么可以使用POST来释放资源,前文说了POST会使得信号量++,离桌的顾客++了以后,没上桌的顾客就得到消息了,PENDING信号量非0,于是未入桌的顾客也吃到饭了。

小结,信号量是用来协调多个线程之间对同一资源的访问,因为

1 同等优先级TASKA TASKB他们的执行顺序不一定,有可能是 ABABABA 顺序,也有可能是BABABA,此时如果有潜在的运行顺序,例如TASKB处理TASKA采集的数据,那么就需要信号量来控制他们的顺序。TASKB一直处于PENDING状态,TASKA数据获取完成后POST信号量。

2 不同优先级 TASK_H 与 TASK_L,调度器自然会一直运行TASK_H,这是必然的,因为TASK_H优先级高,但是我希望TASK_L也能被公正对待,只是任务不重要罢了,不代表不需要运行,此时就可以在TASK_H中POST低优先级任务的信号量,然后进入一段时间的SLEEP,这时低优先级任务得以运行。

信号量的PENDING 和 POST 类似如下代码结构

bool semaphore =0;

for(;;){

       if(!semaphore)//类似PENDING

                return ;//block

       semaphore --;//PENDING 操作会减信号量值

} 

for(;;){

      semaphore++;//类似POST

}

猜你喜欢

转载自blog.csdn.net/Clarence_happy/article/details/89491204