当前位置:文档之家› Small RTOS51中消息队列的一处隐患

Small RTOS51中消息队列的一处隐患

*8566’()*K=中消息队列的一处隐患

"东南大学!!陈皓

引!言

!!52:--?@W5#H是一款专门为N"A#H系列单片机设计的实时操作系统!实际上应该称其为实时内核"#大部分代码用A语言编写#易于移植#十分适合于资源紧张的N位机$同时#它也是学习嵌入式操作系统原理极好的入门材料$本人就是在学习完52:--?@W5#H的基础上进一步学习了著名的R A%W588#受益颇多$

!!问题描述

!!在将52:--?@W5#H应用于实验室某项目时#发现了一个奇怪的问题$简单说来#就是一个以无条件方式申请消息的任务竟然在没有取到消息的情况下#以指示&等待超时’的代码返回了$

!!在这里#首先解释一下任务申请消息的两种方式(无条件方式和超时方式$所谓无条件方式是指任务申请消息时#如果暂时没有消息可取#则任务将一直等待消息#直至取到为止)而超时方式是指任务等待消息是有时间限制的#超过所设定的最大时间#即便没有取到消息#函数也可以正常返回#只是返回值不是消息#而是&超时代码’!此方式可以防止任务因取不到消息而被永久性挂起"$可见#如果任务以无条件方式申请消息#那么函数若能够返回#则说明任务一定是取到消息了#而返回值又怎么可能是&等待超时’呢?经过仔细分析52:--?@W5#H的源代码#找到了问题产生的根源$

!!假定有任务8J V以超时方式调用W5c D.+4!"函数申请消息$W5c D.+4!"函数首先会把8J V放到此消息队列的等待任务表中#然后再去判断队列中是否有消息$最佳情况是队列中确实有消息#则W5c D.+4!"再把8J V从此消息队列的等待任务表中删除#接着W5c D.+4!"返回#任务取到消息$

!!此刻#假定消息队列中没有消息$那么#W5c D.+4!"就会调用W5A-.:)5’E+:-!W5?R++’+E@:/<8J!""和W5K 5(I.4!"这两个系统函数#迫使8J V进入休眠态#同时调度器调度下一个最高优先级的就绪任务来运行$假定任

务8J[被选中#且8J[在运行中通过调用W5c8+,D*/,!"函数向此消息队列发送了一则消息$则W58+,D*/,!"将把所有等待这个消息队列的任务中优先级最高的那个任务唤醒#并且把它从该消息队列的等待任务表中删除#假定它就是8J V$

!!当任务8J[进入休眠态后#操作系统才会调度8J V 来运行$于是8J V从上次被强迫休眠的地方开始运行#即从W5c D.+4!"函数中紧接着W55(I.4!"的那条指令开始执行$具体来说#W5c D.+4!"将首先查看8J V是否满足超时条件!用来判断任务是因为等待超时被唤醒的还是因为确实取到消息而被唤醒的"#若超时时限尚未到达# W5c D.+4!"再接着检查消息队列中是否已经有了消息$根据上面的假定#可以知道任务8J V确实是因为取到消息而被唤醒的$于是#W5c D.+4!"把8J V从此消息队列的等待任务表中删除#W5c D.+4!"正常返回$这样#任务8J V取到消息#接着运行$

!!以上都没有什么问题#但是#有一种情况被忽略了#而正是这种情况的出现导致了任务8J V被长时间挂起#就算队列中有消息存在#8J V也无法被唤醒#只能等到其超时为止$

!!为讨论方便#不妨仍按上述假定情况来分析$当任务8J V被唤醒且8J[进入休眠状态后#系统必将调度下一个优先级最高的就绪任务来运行$在前面#认为这个任务就是8J V#然而此时#假定它是另一个比8J V优先级更高的任务8J e!因为有可能是中断把8J e唤醒的#所以中断退出时#操作系统强制8J[进入休眠态#转而调度8J e运行"$非常巧合的是#8J e在运行的过程中向同一个消息队列也申请了消息$由于之前8J[已经向消息队列发送过一条消息#则8J e将正常取到此条消息$于是#消息队列中的消息数减为"!Y R C*"+]]""$在任务8J e进入休眠后#任务8J V被操作系统调入A D=运行$同样#函数W5c D.+4!"首先查看8J V是否等待超时$如果没有超时#再检查消息队列中是否存在消息$注意到先前已经假定消息被任务8J e给取走了#所以检查的结果当然是队列中不存在消息$8J V就只好再次进入休眠#函数W55(I.4!"

调万方数据

%"

!!""#$%

相关主题
文本预览
相关文档 最新文档