从任务调度机制分析操作系统的实时性

2019-07-13 06:13发布

什么是真正的实时操作系统

        做嵌入式系统开发有一段时间了,做过用于手机平台的嵌入式Linux,也接触过用于交换机、媒体网关平台的VxWorks。实际应用后回过头来看理论,才发现自己理解的肤浅,也发现CSDN上好多同学们都对实时、嵌入式这些概念似懂非懂。毕竟如果不做类似的产品,平时接触的机会很少,即使做嵌入式产品开发,基本也是只管调用Platform Team封装好的API。所以,在此总结一下这些概念,加深自己的理解,同时也给新手入门,欢迎大家拍砖,争取写个连载,本文先总结一下实时的概念,什么是真正的实时操作系统
1. 首先说一下实时的定义及要求:
       参见Donal Gillies在Realtime Computing FAQ中提出定义:实时系统指系统的计算正确性不仅取决于计算的逻辑正确性,还取决于产生结果的时间。如果未满足系统的时间约束,则认为系统失效。        一个实时操作系统面对变化的负载(从最小到最坏的情况)时必须确定性地保证满足时间要求。请注意,必须要满足确定,而不是要求速度足够快!例如,如果使用足够强大的CPU,Windows在CPU空闲时可以提供非常短的典型中断响应。但是,当某些后台任务正在运行时,有时候响应会变得非常漫长,以至于某一个简单的读取文件的任务会长时间无响应,甚至直接挂死。这是一个基本的问题:并不是Windows不够快或效率不够高,而是因为它不能提供确定性,所以,Windows不是一个实时操作系统。        根据实际应用,可以选择采用硬实时操作系统或软实时操作系统。硬实时当然比软实时好,但是,如果你的公司正在准备开发一款商用软件,那请你注意了,业界公认比较好的VxWorks(WindRiver开发),会花光你本来就很少的银子;而软实时的操作系统,如某些实时Linux,一般是开源免费的,我们公司本来的产品就是基于VxWorks的,现在业界都在Cost Reduction,为了响应号召,正在调研如何把平台换成免费的嵌入式实时Linux。同学们,如何选择,自己考虑吧:-) 硬实时 -代表产品 VxWorks        举一个经常使用的实例,中高档汽车中使用的气囊。当报告车辆碰撞的传感器中断CPU后,操作系统应快速地分配展开气囊的任务,并且不允许任何其他非实时处理进行干扰,晚一秒钟展开气囊比没有气囊的情况更糟糕,这就是一个典型的必须使用硬实时的系统。 硬实时系统指系统要有确保的最坏情况下的服务时间,即对于事件的响应时间的截止期限是无论如何都必须得到满足软实时 -代表产品软实时Linux        再举一个实例,IPTV数字电视机顶盒,需要实时的处理(解码)视频流,如果丢失了一个或几个视频帧,显然会造成视频的品质更差,但是只要做过简单的抖动处理的系统,丢失几个视频帧就不会对整个系统造成不可挽救的影响。 软实时系统就是那些从统计的角度来说,一个任务能够得到有确保的处理时间,到达系统的事件也能够在截止期限到来之前得到处理,但违反截止期限并不会带来致命的错误。 =========================================================== 请注意:讲到这里,想花点墨水区分一下实时和嵌入式的概念,因为笔者也长时间把这两者混为一谈。实时操作系统的概念上文已经讲的很清楚了,主要就是要能确定性的满足时间要求。嵌入式系统很难下一个定义,有兴趣的可以百科一下嵌入式系统,一般可以认为是板子或芯片上软硬件的总和嵌入式系统一定要对实时任务有很强的支持能力,所以一般嵌入式系统都会采用实时操作系统,根据不同应用,选择采用硬实时或软实时。 ===========================================================
2. 如何衡量一个实时操作系统的实时性能?
主要有以下两个重要指标: 指标1、中断响应时间(可屏蔽中断)        计算机接收到中断信号到操作系统作出响应,并完成切换转入中断服务程序的时间。对于抢先式内核,要先调用一个特定的函数,该函数通知内核即将进行中断服务,使得内核可以跟踪中断的嵌套。抢先式内核的中断响应时间由下式给出: 中断响应时间=关中断的最长时间+保护CPU内部寄存器的时间+进入中断服务函数的执行时间+开始执行中断服务例程ISR的第一条指令时间 请注意:中断响应时间是系统在最坏情况下响应中断的时间,某系统100次中有99次在50ms之内响应中断,只有一次响应中断的时间是250ms,只能认为中断响应时间是250ms。 指标2、任务切换时间        除为中断处理提供确定性外,实时处理也需要支持周期性间隔的任务调度。大量控制系统要求周期性采样与处理。某个特定任务必须按照固定的周期(p)执行,从而确保系统的稳定性。考虑一下汽车的防抱死系统(ABS)。控制系统对车辆的每个车轮的转速进行采样(每秒最多20次)并控制每个制动器的压力(防止它锁死)。为了保持控制系统的正常工作,传感器的采样与控制必须按照一定的周期间隔。这意味着必须抢占其他处理,以便ABS任务能按照期望的周期执行。         当多任务内核决定运行另外的任务时,它把正在运行任务的当前状态(即CPU寄存器中的全部内容)保存到任务自己的栈区之中。然后把下一个将要运行的任务的当前状态从该任务的栈中重新装入CPU 的寄存器,并开始下一个任务的运行。这个过程就称为任务切换。           做任务切换所需要的时间取决于CPU有多少寄存器要入栈。CPU 的寄存器越多,额外负荷就越重。
系统实时性能重要指标的典型值 --------------------------------------------------------------
              VxWorks     uC/OS-II      RT-Linux2.0   QNX6 硬件平台  MC68000   33MHz-486   60MHz-486    33MHz-486 任务切换  3.8us         <9us             不详               12.57us 中断响应  <3us         <7.5us           25us              7.54us --------------------------------------------------------------
参考文献:《4种实时操作系统实时性的分析对比》。 实时操作系统的核心是任务调度,下面我们来分析一下典型的硬实时代表产品VxWorks和软实时代表产品Linux的任务调度机制。
3. VxWorks的任务调度
        既然实时性对于实时操作系统如此重要,同学们,我们下面就来学习一下实现实时性的核心模块——任务调度。笔者所在的公司花了大把银子购买风河的VxWorks,但是为了实现自己的可控性,除了任务调度模块以外全部重写,包括内存管理、文件管理等其他核心模块,但唯独任务调度模块除外,这可是人家的压箱底法宝:-)        构成应用软件系统的程序集合中,独立的、相互作用的程序单元,在其执行时称之为任务,从系统的角度来看,任务是竞争系统资源的最小运行单元。单个CPU中,多任务机制制造了一个多个任务同时执行的假象。其实系统只是根据一个多任务调度算法,将内核插入到这些任务中执行。实时系统VxWorks的一个任务可有多种状态,但最基本的状态有以下四种: (1)就绪态(Ready):任务只等待系统分配CUP资源。 (2)挂起态(Pend):任务需等待某些不可利用的资源而被阻塞。 (3)休眠态(Sleep):如果系统不需要某一个任务工作,则这个任务处于休眠状态。 (4)延迟态(Delay):任务被延迟时所处的状态。 大家可以在网上搜一下VxWorks任务调度的相关文章,一般都会配状态机图。 --------------------------------------------------------------
请注意:任务task、进程process、线程thread等概念相互联系又相互区别,因为不是本文的重点,这里不多解释,如果想详细了解推荐看一看Windows Kernel Programming。在VxWorks中,因为每个任务没有自己独立的虚拟内存空间,可以把任务理解为线程 --------------------------------------------------------------
      任务由系统内核调度运行一段固定长度的时间,称为时间片(time slice,quantum)。调度是指为任务分配资源和时间,使系统满足特定的性能要求。调度算法的目的是在正常情况下,尽可能满足所有任务的时限:在峰值负载条件下,保证强实时任务满足时限。因为时限是区分实时系统和非实时系统的关键因素,因此调度算法是实时系统的基本问题。实时操作系统所具有的运行性能,如吞吐量的大小、周转时间的长短、相应的及时性和可预测性等在很大程度上都取决于实时调度。 任务调度可采用下述两种方式: (1)非抢占方式。采用这种调度方式,一旦把处理器分配给某任务后,便让该任务一直执行,直到该任务完成或发生某事件而被阻塞,才再把处理器分配给其他任务,决不允许某任务抢占已经分配出去的处理器。显然它难于满足紧急任务的要求,实时系统中不宜采用这种调度方式。 (2)抢占方式。允许调度程序根据某种原则,去停止某个正在执行的任务,将已分配给该任务的处理器,重新分配给另一任务。抢占的原则有: - 时间片原则。各任务按时间片运行,当一个时间片用完后,便停止该任务的执行而重新进行调度。 - 优先权原则。当一个任务到来时,如果其优先级比正在执行的任务的优先级高,便停止正在执行的任务,将处理器分配给优先级高的任务,使之执行。实时系统中一般采用基于优先级的抢占式调度和轮转调度的任务调度和中程调度相结合的调度策略。因此既可具有较大的灵活性,又能获得极小的调度延迟。         VxWorks的wind内核缺省调度机制为基于优先级的抢占式调度。采用这种机制时,系统把处理器分配给优先级最高的任务,使之执行。一旦出现了另一个优先级更高的任务时,任务调度程序剥夺当前任务的执行,将处理器分配给高优先级任务。而在相同优先级的多个任务之间,采用时间片轮转调度机制。采用这种机制时,当一个任务到达时,它被排在轮转队列的后面,等待分配给自己的时间片的到来,如果在时间片内没有结束,则再等待属于自己的时间片的到来,直到任务完成。 - 优先级抢占式        采用基于优先级的抢占式调度,系统中每个任务都有一个介于最高0到最低255之间的优先级。任一时刻,系统内核一旦发现一个优先级更高的任务转变为就绪态,内核就保存当前任务的上下文并把当前任务状态转换为阻塞态,同时切换到这个高优先级任务的上下文执行。 - 轮转调度算法        采用轮转调度算法,系统让处于就绪态的优先级相同的一组任务依次轮流执行预先确定长度的时间片。这是一种处理器平均分配的方法。如果不使用轮转调度算法,优先级相同的一组任务中第一个获得处理器的任务将不会被阻塞而独占处理器,如果没有阻塞或其他情况发生,它不会放弃处理器的使用权。 - 抢占调度与轮转调度混合方式        有时,基于优先级的抢占式调度可与轮转调度相结合。当优先级相同的一组任务依次轮流平均分配处理器时,若有高优先级的任务转变为就绪态则可抢占该组任务。直到再一次符合执行条件时,该组任务才可再次共享处理器。         为了任务控制的灵活性,VxWorks内核还提供了动态优先级机制,任务的优先级在运行期间可动态地变化。同时,为了防止优先级反转,还具有优先级继承机制,通过使用互斥信号量可以防止高优先级的任务被迫等待一段不确定时间,直到一个低优先级任务完成。 参考文献:《实时操作系统VxWorks的内核任务调度研究》。
4. Linux的任务调度
       通用Linux系统支持实时非实时两种进程,实时进程相对于普通进程具有绝对的优先级。对应地,实时进程采用SCHED_FIFO或者SCHED_RR调度策略,普通的进程采用SCHED_OTHER调度策略。        在调度算法的实现上,Linux中的每个任务有四个与调度相关的参数,它们是rt_priority、policy、priority(nice)、counter。调度程序根据这四个参数进行进程调度。        在SCHED_OTHER调度策略中,调度器总是选择那个priority+counter值最大的进程来调度执行。从逻辑上分析SCHED_OTHER调度策略存在着调度周期(epoch),在每一个调度周期中,一个进程的priority和counter值的大小影响了当前时刻应该调度哪一个进程来执行,其中priority是一个固定不变的值,在进程创建时就已经确定,它代表了该进程的优先级,也代表这该进程在每一个调度周期中能够得到的时间片的多少counter是一个动态变化的值,它反映了一个进程在当前的调度周期中还剩下的时间片。在每一个调度周期的开始,priority的值被赋给counter,然后每次该进程被调度执行时,counter值都减少。当counter值为零时,该进程用完自己在本调度周期中的时间片,不再参与本调度周期的进程调度。当所有进程的时间片都用完时,一个调度周期结束,然后周而复始。另外可以看出Linux系统中的调度周期不是静态的,它是一个动态变化的量,比如处于可运行状态的进程的多少和它们priority值都可以影响一个epoch的长短。值得注意的一点是,在2.4以上的内核中,priority被nice所取代,但二者作用类似。        可见SCHED_OTHER调度策略本质上是一种比例共享的调度策略,它的这种设计方法能够保证进程调度时的公平性--一个低优先级的进程在每一个 epoch中也会得到自己应得的那些CPU执行时间,另外它也提供了不同进程的优先级区分,具有高priority值的进程能够获得更多的执行时间。对于实时进程来说,它们使用的是基于实时优先级rt_priority的优先级调度策略,但根据不同的调度策略,同一实时优先级的进程之间的调度方法有所不同: - SCHED_FIFO:不同的进程根据静态优先级进行排队,然后在同一优先级的队列中,谁先准备好运行就先调度谁,并且正在运行的进程不会被终止直到以下情况发生:(1).被有更高优先级的进程所强占CPU;(2).自己因为资源请求而阻塞;(3).自己主动放弃CPU(调用sched_yield)。 - SCHED_RR:这种调度策略跟上面的SCHED_FIFO一模一样,除了它给每个进程分配一个时间片,时间片到了正在执行的进程就放弃执行;时间片的长度可以通过sched_rr_get_interval调用得到。
由于Linux系统本身是一个面向桌面的系统,所以将它应用于实时应用中时存在如下的一些问题: - Linux系统中的调度单位为10ms,所以它不能够提供精确的定时; - 当一个进程调用系统调用进入内核态运行时,它是不可被抢占的; - Linux内核实现中使用了大量的锁中断操作会造成中断的丢失; - 由于使用虚拟内存技术,当发生页出错时,需要从硬盘中读取交换数据,但硬盘读写由于存储位置的随机性会导致随机的读写时间,这在某些情况下会影响一些实时任务的截止期限; - 虽然Linux进程调度也支持实时优先级,但缺乏有效的实时任务的调度机制和调度算法;它的网络子系统的协议处理和其它设备的中断处理都没有与它对应的进程的调度关联起来,并且它们自身也没有明确的调度机制; 参考文献:《基于Linux的实时系统》。
5.Windows的任务调度        Windows是一款微内核、抢占式多任务、软实时的操作系统。Windows的任务调度主要以线程为单位进行,线程拥有33个优先级,数值为0~32,其中0为最低优先级,32为最高优先级,最高和最低优先级均保留给系统使用。用户可以使用的优先级为1~31。       Windows按照优先级高低顺序来进行任务的调度,当调度发生时,内核首先检查高优先级的线程是否就绪,如果有发现有高优先级的线程就绪则立刻将高优先级的线程发往CPU执行。如果有高优先级的线程就绪,就不会执行低优先级的任务。不 过,windows使用成为“饥渴”的时间片分配策略,如果有线程一直渴望得到时间片但是很长时间都没有获得时间片,windows就会临时将这个线程的 优先级提高,并一次分配给2倍的时间片来执行,但是windows绝不会将这个线程的优先级提高到实时优先级范围(16~31为实时优先级范围),如果不希望windows进行饥渴分配策略,也可以通过特定的API将该策略关闭(SetThreadPriorityBoost)。       Windows同时采用时间片策略来执行相同优先级的任务。相同优先级的线程会获得同样的时间片(一般为2个系统Tick,在单CPU系统上一个系统Tick一般为10ms,多CPU系统上一般为15ms,可以通过 GetSystemTimeAdjustment查询)。一个线程的时间片用完后,Windows会将另外一个已经就绪的同优先级的线程发往CPU进行执行。正在执行的线程将在线程中主动放弃时间片(比如调用Sleep函数),时间片用完或Windows发现有更高优先级的线程就绪后暂停执行。      另外,Windows还存在不受优先级策略控制的线程,如DPC的处理线程,Windows中每个CPU上都有一个DPC队列,只要DPC中有等待处理的任务,Windows总是会立刻对DPC中的任务进行处理。       Windows和硬实时操作系统的区别在于,硬实时操作系统一般拥有256或更多的优先级,硬实时操作系统的最重要特性在于中断的处理方式方面,Windows使用DPC队列方式来延时处理中断请求,在ISR中仅能执行时间非常关键的硬件寄存器操作(如恢复清除设备中断寄存器使得设备能进行下一次中断),DPC队列按照先入先出的方式执行,这样如果系统在短时间发生大量中断而使得DPC队列中存在大量待处理的中断请求时,时间关键的中断请求可能会在很长时间后才得到处理,使得系统丧失实时响应能力。硬实时操作系统的ISR同样一般仅能执行时间关键的硬件寄存器操作,也必须通过任务调度切换至相关的任务上下文环境,才能访问更多的资源来进行相关的处理,但是硬实时操作系统可以根据优先级来处理中断的请求, 后发生的高优先级中断请求可以抢占低优先级中断或低优先级任务的时间片,而使得时间关键的中断请求总是能得到最优先的处理。       对各种操作系统的任务调度策略进行深入的理解之后,才能对一套应用系统的设计进行精确的把握。 Windows的调度策略很适合处理各种非事件性的数据,比如大量的流数据,可以达到很高的数据吞吐量。如果你设计的系统是需要实时响应的中断事件式的处理,那么你可能需要考虑使用一款硬实时的操作系统,如Windows CE 5.0以上版本,或vxWorks,WindowsCE有很好的硬实时的处理能力,价格低廉,开发容易,缺点是可用软件少。而vxWorks功能强大,有庞大的gnu软件阵容做后盾,唯一美中不足的是价格昂贵。其他免费的操作系统只会令你的项目陷入困境,如果做的是有的是时间没有钱的项目,才值得考虑。 6.μC/OS-II的任务调度        μC/OS-II操作系统的任务状态有五种,分别是睡眠态、就绪态、运行态、等待状态和中断服务态。         μC/OS-II操作系统总是运行进入就绪态任务中优先级最高的任务。它可以管理多达64个任务,但目前的版本里已经有两个任务被系统占用。一般来说用户可以使用从优先级4到优先级OS_LOWEST_PRIO-4一共56个优先级。对于多任务的管理,μC/OS-II操作系统是通过调度器完成了。其中任务级的调度是由函数OSSched()完成,而中断级的调度是通过函数OSIntExiT()完成。这两个函数是很相似的,所不同的其中一点就是OSSched()调用了任务切换函数OS_TASK_SW(),而退出中断服务子程序OSIntExiT()却调用的是OSIntCtxSw()函数。这是因为中断服务子程序已经将CPU寄存器存入到中断了的任务的堆栈中,所以只需要恢复堆栈中的内容即可。
        μC/OS-II操作系统是一个商业用的实时操作系统。这是因为它是可剥夺型内核。可剥夺型内核是指当有高优先级任务到来时,不用等待低优先级的任务执行完毕,可以直接切换到高优先级的任务执行,即高优先级任务可以剥夺低优先级任务的CPU的使用权。μC/OS-II操作系统是一个多任务的实时操作系统。对于多任务的调度,它主要通过以下四类方法的使用来完成。 
  1优先级 
  对于μC/OS-II操作系统定义的每一个任务,在创建任务之初,一定会给这个任务分配一个合适的优先级。如果一个操作系统在调度算法选择上只是基于优先级调度,即支持静态优先级,那么这个操作系统只是一个准实时操作系统。而在μC/OS-II操作系统中,任务的优先级是可变的,即支持动态优先级。因此μC/OS-II操作系统是一个实时操作系统。改变任务优先级的函
数是OSTaskChangePrio()。 
  2互斥信号量与信号量 
  在μC/OS-II操作系统中,互斥信号量被定义为一个二值信号,可以实现对共享资源的独占式占用。当这个资源被一个任务占用时,就被定义为1。其他的需要这个资源的任务如果检查到互斥型信号量是1,则进入等待状态,当占用此资源的任务释放这个资源时,互斥型信号量则被置为0,此时等待这个资源的任务队列中优先级最高的任务则可以获得这个资源而得以执行。 
  在μC/OS-II操作系统中,信号量有两种用法:一种是执行与互斥信号量相同的功能。二是如果一个资源允许多个任务调用,但现在要调用此资源的任务数目却多于允许使用此资源的数目,此时就需要用到信号量。这种情况下就会为资源设置一个计数器,如果被一个任务调用一次就自动减一,被一个任务释放一次就自动加一,只要这个计数器是大于零的,其他的任务就可以调用这个资源。 
  3消息邮箱和消息队列 
  用来传递消息缓冲区指针的数据结构叫做消息邮箱。消息邮箱所传递的是指向消息的指针,并非消息本身。如果一个任务获得了这个指针,即获得了该指针指向的一个特定数据结构。 
  消息邮箱不仅用来传递一个消息,而且也可定义一个指针数组,让数组的每个元素都存放一个消息缓冲区指针。那么任务就可通过这个指针数组指针的方法来传递多个消息。这种可以传递多个消息的数据结构叫做消息队列。 
  消息邮箱和消息队列在功能上的不同点是邮箱中只能存放一则消息指针,而队列可以存放多则消息指针。 
  4事件标志组 
  当某个任务需要与多个任务同步时,必须要使用事件标志组。事件标志组一旦建立之后,只有当某个任务需要事件标志组中的某些事件标志位(置位或者清0),这个任务才能继续运行。而且几个任务可以同时得到所需要的事件标志而进入就绪态。因此只要任务所需要的标志位满足要求,任务便可以进入就绪态。而使用信号量的任务是在等待该信号量的任务中优先级最高的任务才能得到信号量进入就绪态。 
  事件标志组可以使一个任务与多个任务同步,而信号量只能使一个任务与另一个任务同步。这是事件标志组与信号量的不同之处。 

        进一步分析参考:再说经典:μC/OS-IIμC/OS-II的实时性能分析 实时操作系统μC/OS-II任务调度机制的分析与改进
7.实时Linux研究
       呼哧呼哧写了半天,终于到了重头戏,实时Linux研究。前文说过,风河的VxWorks虽然性能大大的好,但是要花很多银子,对于一般的软实时应用系统来说,还是用开源免费的实时Linux比较好。笔者所在的公司也正在研究将平台转为Linux。有许多种方法可以赋予普通Linux实时的能力: 瘦内核(微内核)- Thin-Kernel        瘦内核(或微内核)方法使用了第二个内核作为硬件与Linux内核间的抽象接口。非实时Linux内核在后台运行,作为瘦内核的一项低优先级任务托管全部非实时任务。实时任务直接在瘦内核上运行。瘦内核主要用于(除了托管实时任务外)中断管理。瘦内核截取中断以确保非实时内核无法抢占瘦内核的运行。这允许瘦内核提供硬实时支持。
        虽然瘦内核方法有自己的优势(硬实时支持与标准Linux内核共存),但这种方法也有缺点。实时任务和非实时任务是独立的,这造成了调试困难。而且,非实时任务并未得到Linux平台的完全支持(瘦内核之所以称为的一个原因)。使用这种方法的例子有RTLinux(现在由Wind River Systems专有),实时应用程序接口(RTAI)和Xenomai。 超微内核        这里瘦内核方法依赖于包含任务管理的最小内核,而超微内核法对内核进行更进一步的缩减。通过这种方式,它不像是一个内核而更像是一个硬件抽象层(HAL)。超微内核为运行于更高级别的多个操作系统提供了硬件资源共享。因为超微内核对硬件进行了抽象,因此它可为更高级别的操作系统提供优先权,从而支持实时性。
       注意,这种方法和运行多个操作系统的虚拟化方法有一些相似之处。使用这种方法的情况下,超微内核在实时和非实时内核中对硬件进行抽象。这与 hypervisor 从客户(guest)操作系统对裸机进行抽象的方式很相似。        关于超微内核的示例是操作系统的Adaptive Domain Environment for Operating Systems(ADEOS)。ADEOS支持多个并发操作系统同步运行。当发生硬件事件后,ADEOS对链中的每个操作系统进行查询以确定使用哪一个系统处理事件。 资源内核(Resource-kernel        另一个实时架构是资源内核法。这种方法为内核增加一个模块,为各种资源提供预留(reservation)。这种机制保证了对时分复用(time- multiplexed)系统资源的访问(CPU、网络或磁盘带宽)。这些资源拥有多个预留参数,如循环周期、需要的处理时间(也就是完成处理所需的时间),以及截止时间。
       资源内核提供了一组应用程序编程接口(API),允许任务请求这些预留资源。然后资源内核可以合并这些请求,使用任务定义的约束定义一个调度,从而提供确定的访问(如果无法提供确定性则返回错误)。通过调度算法,如Earliest-Deadline-First(EDF),内核可以处理动态的调度负载。        资源内核法实现的一个示例是CMU公司的Linux/RK,它把可移植的资源内核集成到Linux中作为一个可加载模块。这种实现演化成商用的 TimeSys Linux/RT 产品。 标准的Linux内核最新版本2.6中加入了实时功能        目前探讨的这些方法在架构上都很有趣,但是它们都在内核的外围运行。然而,如果对标准Linux内核进行必要的修改使其支持实时性,结果会怎么样呢?        今天,在2.6内核中,通过对内核进行简单配置使其完全可抢占,您就可以得到软实时功能。在标准2.6 Linux内核中,当用户空间的进程执行内核调用时(通过系统调用),它便不能被抢占。这意味着如果低优先级进程进行了系统调用后,高优先级进程必须等到调用结束后才能访问CPU。        新的配置选项CONFIG_PREEMPT改变了这一内核行为,在高优先级任务可用的情况下(即使此进程正在进行系统调用),它允许进程被抢占。
       但这种配置选项也是一种折衷。虽然此选项实现了软实时性能并且即使在负载条件下也可使操作系统顺利地运行,但这样做也付出了代价。代价就是略微减低了吞吐量以及内核性能,原因是CONFIG_PREEMPT选项增加了开销。这种选项对桌面和嵌入式系统而言是有用的,但并不是在任何场景下都有用(例如,服务器)。        在2.6内核中另一项有用的配置选项是高精度定时器。这个新选项允许定时器以1μs的精度运行(如果底层硬件支持的话),并通过红黑树实现对定时器的高效管理。通过红黑树,可以使用大量的定时器而不会对定时器子系统(O(log n))的性能造成影响。 只需要一点额外的工作,就可以通过PREEMPT_RT补丁实现硬实时。PREEMPT_RT补丁提供了多项修改,可实现硬实时支持。其中一些修改包括重新实现一些内核锁定原语,从而实现完全可抢占,实现内核互斥的优先级继承,并把中断处理程序转换为内核线程以实现线程可抢占。 参考文献:《实时Linux架构剖析》 - M. Tim Jones, 顾问工程师, Emulex Corp. 8.实时性比较        几种嵌入式实时操作系统的分析与比较
参考:
从软实时到硬实时》 《硬实时和软实时区别》 《“硬实时”为Linux注入新活力》 
T-Kernel 任务调度的实时性分析线程的调度
实时操作系统的任务调度原因分析
linux任务调度机制
Linux与VxWorks任务调度机制分析
时间系统、进程的调度与切换