版权声明:本文为博主(张家越)原创文章,欢迎转载,但请务必注明出处和作者!
我与2015年6月进入了一家从事车载产品研发,设计的公司。进入公司之后便开始接触和学习状态机编程,主要原因是公司之前的代码使用了状态机的框架。到目前为止接触状态机已经有差不多一年的时间了,今天之所以写这篇博客,一是为了对这一年多使用状态机的经验做个总结,二是希望可以给正在学习和使用状态机的爱好者,提供一些帮助和参考!
我目前使用的状态机框架是国内一位大牛写的(jorya_txj),该作者的主要产品是实时操作系统(RAW_OS),和一些其它代码产品,我所说的状态机,在作者官网上的名称叫“事件触发系统”,具体细节可以访问他的官方网站进行了解。http://www.raw-os.org/
现在进入正题,本文主要从用户编程的角度去讨论状态机的特点,状态机内核代码实现了,简单的任务间通信,基于优先级的非抢占式任务调度,和系统延时。由于内核主要实现了上述三个功能,所以它的代码量非常小,可以运行在RAM和ROM都非常有限的CPU上。相对于UCOSII这类实时操作系统来说,代码的理解难度也要小很多。但是它代码编写的规范性比UCOSII也确实差一个档次,这是我在看完源代码之后的一个最深切的感受,呵呵呵呵,在这里吐槽一下!好在功夫不负有心人,只要你多下点功夫,看懂整个程序的来龙去脉也不是很难,毕竟它只有这么点功能!
接下来我们从6个方面来比较它们的异同:
一.状态机和UCOSII创建一个任务有什么相同点和不同点?
先来说相同点: 都需要指定任务的优先级,都需要为每个任务指定独立的栈空间
再来看区别: UCOSII的每个任务都是一个死循环,所以它需要任务中主动来调用延时函数或者等待信号量、消息邮箱、消息队列,来交出CPU的使用权,状态机的每个任务都只执行一次
二.状态机和UCOSII任务切换过程有什么相同点和不同点?
在这个问题上,它们基本没有相同点,下面我们就来先看看UCOSII是怎么进行任务切换的,UCOSII的任务是一个死循环,大家先来想这样一个问题,怎么才能暂停一个死循环的函数,去执行另外一个死循环的函数呢?采用中断,只有中断才能打断一个死循环,那具体是怎么操作的呢?如果有更高优先级的任务等待运行,CPU会在中断函数中(UCOSII使用PenSV中断进行任务切换),先将被终止任务的断点指针和CPU通用寄存器压入栈中,再把带运行任务栈中的数据,恢复到CPU寄存器中,让CPU获得待运行任务的断点指针,从而实现任务切换。
状态机的任务切换,是在当前任务执行完成之后,查询就绪状态的最高优先级任务,然后根据优先级获得,该任务的函数指针,最后去调用该函数,状态机的任务切换相比UCOSII要简单很多!
三.状态机和UCOSII发生任务切换的时间点有什么相同点和不同点呢?
在这个问题上,它们基本也没有相同点,下面我们就来先看看UCOSII发生任务切换的时间点:
1.系统的一个时钟节拍到了之后,会在滴答定时器中断中触发一次任务调度,如果有更高优先级的任务进入了就绪状态,就会发生一次任务切换(任务切换是依靠触发PendSV_Handler来实现的)
2.当用户任务调用系统延时函数时,会挂起当前任务,触发一次任务调度,转而去运行已经就绪的最高优先级任务
3.退出中断服务函数之前,会检查是否有更高优先级的任务已经就绪,如果有则进行任务切换,没有则恢复之前的任务运行
4.当用户在任务中请求一个信号量,消息邮箱或者消息队列,而此时没有等到请求的信号量,消息邮箱或者消息队列,改任务会被挂起,然后去执行此时已经处于就绪状态的最高优先级任务。
5.当用户在任务中发送一个信号量,消息邮箱或者消息队列时,UCOSII内核会先去判断是否有任务正在等待该信号量,消息邮箱或者消息队列,如果有,则先将该等待任务置为就绪状态,然后发生一次任务调度,去运行已经就绪的最高优先级任务
状态机发生任务切换的时间点:
1.当前优先级任务执行完成之后,会先将当前任务置为挂起状态,然后去查找就绪的最高优先级任务,最后切换到最高优先级任务去执行。
四.使用状态机和UCOSII哪种方式效率更高,更适合在嵌入式系统中使用?
UCOSII的优点:
1.UCOSII是基于优先级的抢占式调度方式,高优先级的任务可以得到更快的响应速度
2.UCOSII具有更高的任务调度频率,任务的实时性会更强
UCOSII的缺点:
1.抢占式调度方式,要求用户在使用全局变量时要特别小心,因为全局变量在修改的过程中可能会被中断打断,如果在被打断之后,又在新的任务中操作了该全局变量,该变量的值,在中断返回之后可能会出错!
2.UCOSII具有更高的调度频率,操作系统会消耗更多的CPU时间
状态机的优点:
1.它是基于优先级的非抢占式调度方式,低优先级的任务不会在运行的过程中被打断,在不同任务间使用全局变量,没有出错的风险!
2.非抢占式调度,在任务调度上,会消耗更少的CPU时间
状态机的缺点:
1.非抢占式调度方式,高优先级任务的响应速度会比ucosii慢。
2.非抢占式调度方式,不能有执行时间特别长的任务,否则会导致高优先级任务响应非常缓慢,因为如果的优先级任务已经运行,此时高优先级任务就绪了,但是它却不能立即抢占,需要等到已经运行的低优先级任务执行完毕,所有在使用状态机时,这一点必须特别注意!
总结:从应用的角度来讲,这两种任务调度机制各有优势和缺点,UCOSII具有更强的实时性,但是程序设计过程中一定要注意全局变量的保护,尽量少使用或者不使用全局变量,状态机编程没有此限制;状态机的实时性稍微差一点,但是只要在程序设计过程中注意,保证每个任务的执行时间都很短,依然可以得到很快的响应速度和实时性,因为状态机的调度频率较低,系统占用的CPU时间相对较少。
本文就先写到这里,由于笔者水平有限,文中难免会有错误和疏漏之处,恳请广大读者提出宝贵意见。
作者:张家越
时间:2016-05-17