实时任务调度器是实时操作系统的一个必选项,列举措施如下(ucos为例):
1、抢占式内核机制:
抢占,顾名思义就是支持对CPU使用权的争抢。只有CPU开放了使用权的争抢,才能有效保证那些紧急的事件能够尽快的得到相应。如果大家都是按照传统时间片的方式分享使用CPU使用权,那么一些内部管理的任务,比如ucos的idle,统计任务等等都会因为占有时间片影响了紧急事件对CPU的使用和调配。
2、中断响应+优先级机制:
在嵌入式系统运行的过程中,CPU是如何与外部事件进行交互的呢?换句话说,CPU怎么知道外面发生了什么事情?中断的作用就体现在这里。如果CPU越快的知道事件发生,就有可能最快的速度处理,那么实时性肯定也就越高。丰富的中断机制和多级优先级机制,有效保证了紧急的事件优先处理,对实时性的提高非常有帮助。
3、轻量化的任务调度机制:
ucos的任务调度,主要依靠中断触发和软中断触发两种。核心的调度代码,仅仅是汇编编写的几十行。能不能想象到?就几十行汇编代码就支撑了整个ucos的任务调度。与linux的内核调度机制相比较,轻量化的太多太多!可以说,如此轻量级别的内核任务调度,极大的提高了CPU任务切换的速度,实时性又怎能不高呢?
实时系统的实时性不代表只要设计出来一个实时调度器就足够了。事实上设计一个实时调度内核并不是一个多么复杂的任务,实时操作系统的特性是在整个操作系统的设计思路上都要时刻关注实时性。
只有一个实时内核的操作系统,一般只能算作“软实时”。
硬实时系统,系统中的大部分组件,包括并不限于:文件系统、网络、总线驱动、IO框架等,都是面向实时设计的。
例子1:实时系统中很少会用到线程池的概念,因为线程池的调度存在着很大的不确定性。假设现在有4个线程的线程池,被优先级100的任务使用,此时有一个优先级是50的任务申请线程池资源,但线程池已经没有空闲的线程了,只能等待,不符合实时系统的设计。
例子2:实时系统中一般不会用到虚拟内存(内存页面交换到磁盘)。因为发生缺页中断以后,从磁盘读取缺页内容,再载入内存的过程非常缓慢且不确定,会导致整个任务执行时间不确定。
例子3:无锁设计的软件在实时系统中不一定能正常工作,因为无锁设计的软件一般使用原子操作代替锁,防止死锁实际上是要依赖于操作系统的时间片轮转调度,但时间片轮转调度在RTOS里不是一个必需的,所以无锁设计在RTOS上反而容易死锁:
例子4:实时系统的各种协议栈(比如TCP/IP)往往没有或者很少使用异步线程/异步请求设计(除非是用户代码直接使用异步IO的借口)。桌面操作系统中,一些系统调用请求,会被转化成一个新的内核线程(或者挂到一个请求队列里),这种动作会造成实时性的波动。实时系统的一些系统调用,往往是直接从用户态一直走到驱动,都是在同一个调用栈(上下文),来保证请求的实时性。
例子5:一些极端的实时系统(比如飞控系统),会在系统启动以后禁用malloc/free来防止系统中的不确定性。
例子6:实时系统里的spinlock可能是task(thread) level的。一般来说,用上了spinlock,一般都会关中断,但RTOS里,会提供task级别的spinlock,这种spinlock不是真正的关闭中断(系统仍然能响应中断,挂到中断处理队列里),但仍然从软件级别上,保证跟spinlock一样的效果。
例子7:实时系统的ISR handler可能是task(thread) level的。一般来说,挂到中断ISR上的函数,都是运行在中断上下文里的,但这个handler执行期间会关中断,如果handler代码太长,那么关中断的时间就会太长,所以实时系统会提供task级别的ISR handler,进一步保证系统能足够快的响应中断。
关于实时系统,有很多人有错误的认知:
1. 实时系统一定很快,错误。实时系统不一定快,相反的,实时系统的效率往往不高,如果系统中存在着周期性的高优先级任务,往往会导致实时系统的低优先级任务被周期性的打断,造成整个系统吞吐量下降(比如机械硬盘访问,高低任务交叉执行会导致磁头反复移动,效率降低)。
2. 实时系统一定很小,代码精简,错误。现在大型的实时系统已经很大了,一个操作系统的代码中,规模最大的往往是各种驱动,现代实时操作系统因为要支持多种硬件平台,驱动规模不会太小。
3. 实时系统里不能有delay/sleep操作,错误。实时系统里可以有delay的,因为delay可能是用户行为,delay本身也是一个确定性的操作,实时系统里应该避免不确定的delay动作。
实时系统的设计原则是要避免不确定性的设计,实时系统可以很慢,效率可以低,确定性才是必须的。你可以写一个很垃圾的算法的调度器代码,放到RTOS里跑,没有问题的,算法是否垃圾,不是检测它是不是一个RTOS的基本原则。但是如果这个垃圾代码里,包含不确定的长期关中断、关调度的行为,那么这个代码就是不符合RTOS原则的。