出自:http://blog.csdn.net/zhourui1982/article/details/5282361linux
作嵌入式系统开发有一段时间了,作过用于手机平台的嵌入式Linux,也接触过用于交换机、媒体网关平台的VxWorks,实际应用后回过头来看理论,才发现本身理解的肤浅,也发现CSDN上好多同窗们都对实时、嵌入式这些概念似懂非懂,毕竟若是不作相似的产品,平时接触的机会不多,即便作嵌入式产品开发,基本也是只管调用Platform team封装好的API。因此在此总结一下这些概念,加深本身的理解,同时也给新手入门,欢迎你们拍砖,争取写个连载,本文先总结一下实时的概念,什么是真正的实时操做系统?算法
1. 首先说一下实时的定义及要求:编程
参见 Donal Gillies 在 Realtime Computing FAQ 中提出定义:实时系统指系统的计算正确性不只取决于计算的逻辑正确性,还取决于产生结果的时间。若是未知足系统的时间约束,则认为系统失效。
http://www.faqs.org/faqs/realtime-computing/faq/服务器
一个实时操做系统面对变化的负载(从最小到最坏的状况)时必须肯定性地保证知足时间要求。请注意,必需要知足肯定性,而不是要求速度足够快!例如,若是使用足够强大的CPU,Windows在CPU空闲时能够提供很是短的典型中断响应,可是,当某些后台任务正在运行时,有时候响应会变得很是漫长,以致于某一个简单的读取文件的任务会长时间无响应,甚至直接挂死。这是一个基本的问题:并非Windows不够快或效率不够高,而是由于它不能提供肯定性,因此,Windows不是一个实时操做系统。网络
根据实际应用,能够选择采用硬实时操做系统或软实时操做系统,硬实时固然比软实时好,可是,若是你的公司正在准备开发一款商用软件,那请你注意了,业界公认比较好的VxWorks(WindRiver开发),会花光你原本就不多的银子,而软实时的操做系统,如某些实时Linux,通常是开源免费的,咱们公司原本的产品就是基于VxWorks的,如今业界都在Cost Reduction,为了响应号召,正在调研如何把平台换成免费的嵌入式实时Linux。同窗们,如何选择,本身考虑吧:-)数据结构
硬实时 - 表明产品 VxWorks 架构
举一个常用的实例,中高档汽车中使用的气囊。当报告车辆碰撞的传感器中断CPU后,操做系统应快速地分配展开气囊的任务,而且不容许任何其余非实时处理进行干扰,晚一秒钟展开气囊比没有气囊的状况更糟糕,这就是一个典型的必须使用硬实时的系统。 并发
硬实时系统指系统要有确保的最坏状况下的服务时间,即对于事件的响应时间的截止期限是不管如何都必须获得知足。 函数
软实时 - 表明产品 软实时Linux 性能
再举一个实例,IPTV数字电视机顶盒,须要实时的处理(解码)视频流,若是丢失了一个或几个视频帧,显然会形成视频的品质更差,可是只要作过简单的抖动处理的系统,丢失几个视频帧就不会对整个系统形成不可挽救的影响。
软实时系统就是那些从统计的角度来讲,一个任务可以获得有确保的处理时间,到达系统的事件也可以在截止期限到来以前获得处理,但违反截止期限并不会带来致命的错误。
---------------------------------------------
请注意:讲到这里,想花点墨水区分一下实时和嵌入式的概念,由于笔者也长时间把这二者混为一谈。实时操做系统的概念上文已经讲的很清楚了,主要就是要能肯定性的知足时间要求。嵌入式系统很难下一个定义,有兴趣的能够百科一下“嵌入式系统”,通常能够认为是板子或芯片上软硬件的总和,嵌入式系统必定要对实时任务有很强的支持能力,因此通常嵌入式系统都会采用实时操做系统,根据不一样应用,选择采用硬实时或软实时。
---------------------------------------------
2. 如何衡量一个实时操做系统的实时性能?
主要有如下两个重要指标:
指标一、中断响应时间(可屏蔽中断)
计算机接收到中断信号到操做系统做出响应,并完成切换转入中断服务程序的时间。对于抢先式内核,要先调用一个特定的函数,该函数通知内核即将进行中断服务,使得内核能够跟踪中断的嵌套。抢先式内核的中断响应时间由下式给出:
中断响应时间=关中断的最长时间+保护CPU 内部寄存器的时间+进入中断服务函数的执行时间+开始执行中断服务例程(ISR)的第一条指令时间
请注意:中断响应时间是系统在最坏状况下响应中断的时间,某系统100次中有99次在50ms以内响应中断,只有一次响应中断的时间是250ms,只能认为中断响应时间是250ms。
指标二、任务切换时间
除为中断处理提供肯定性外,实时处理也须要支持周期性间隔的任务调度。大量控制系统要求周期性采样与处理。某个特定任务必须按照固定的周期(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种实时操做系统实时性的分析对比》 - 百度一下能够搜到
3. 实时操做系统的核心 - 任务调度(VxWorks)
既然实时性对于实时操做系统如此重要,同窗们,咱们下面就来学习一下实现实时性的核心模块 - 任务调度。笔者所在的公司花了大把银子购买风河的VxWorks,可是为了实现本身的可控性,除了任务调度模块之外所有重写,包括内存管理、文件管理等其余核心模块,但惟独任务调度模块除外,这但是人家的压箱底法宝:-)
构成应用软件系统的程序集合中,独立的、相互做用的程序单元,在其执行时称之为任务,从系统的角度来看,任务是竞争系统资源的最小运行单元。单个CPU 中,多任务机制制造了一个多个任务同时执行的假象。其实系统只是根据一个多任务调度算法,将内核插入到这些任务中执行。实时系统VxWorks的一个任务可有多种状态,但最基本的状态有如下四种:
1) 就绪态(Ready):任务只等待系统分配CUP资源。
2) 挂起态(Pend):任务需等待某些不可利用的资源而被阻塞。
3) 休眠态(Sleep):若是系统不须要某一个任务工做,则这个任务处于休眠状态。
4) 延迟态(Delay):任务被延迟时所处的状态。
你们能够在网上搜一下VxWorks任务调度的相关文章,通常都会配状态机图。
----------------------------
请注意:任务(task)、进程(process)、线程(thread)等概念相互联系又相互区别,由于不是本文的重点,这里很少解释,若是想详细了解推荐看一看“Windows Kernel Programming”。在VxWorks中,由于每一个任务没有本身独立的虚拟内存空间,能够把任务理解为线程。
----------------------------
任务由系统内核调度运行一段固定长度的时间,称为时间片。调度是指为任务分配资源和时间,使系统知足特定的性能要求。调度算法的目的是在正常状况下,尽量知足全部任务的时限:在峰值负载条件下,保证强实时任务知足时限。由于时限是区分实时系统和非实时系统的关键因素,所以调度算法是实时系统的基本问题。实时操做系统所具备的运行性能,如吞吐量的大小、周转时间的长短、相应的及时性和可预测性等在很大程度上都取决于实时调度。
进程调度可采用下述两种方式:
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. 实时Linux研究
呼哧呼哧写了半天,终于到了重头戏,实时Linux研究。前文说过,风河的VxWorks虽然性能大大的好,可是要花不少银子,对于通常的软实时应用系统来讲,仍是用开源免费的实时Linux比较好。笔者所在的公司也正在研究将平台转为Linux。有许多种方法能够赋予普通Linux实时的能力:
5.1 瘦内核(微内核)- Thin-Kernel
瘦内核(或微内核)方法使用了第二个内核做为硬件与 Linux 内核间的抽象接口。非实时 Linux 内核在后台运行,做为瘦内核的一项低优先级任务托管所有非实时任务。实时任务直接在瘦内核上运行。瘦内核主要用于(除了托管实时任务外)中断管理。瘦内核截取中断以确保非实时内核没法抢占瘦内核的运行。这容许瘦内核提供硬实时支持。
虽然瘦内核方法有本身的优点(硬实时支持与标准 Linux 内核共存),但这种方法也有缺点。实时任务和非实时任务是独立的,这形成了调试困难。并且,非实时任务并未获得 Linux 平台的彻底支持(瘦内核执行称为瘦 的一个缘由)。
使用这种方法的例子有 RTLinux (如今由 Wind River Systems 专有),实时应用程序接口(RTAI)和 Xenomai。
5.2 超微内核
这里瘦内核方法依赖于包含任务管理的最小内核,而超微内核法对内核进行更进一步的缩减。经过这种方式,它不像是一个内核而更像是一个硬件抽象层(HAL)。超微内核为运行于更高级别的多个操做系统提供了硬件资源共享。由于超微内核对硬件进行了抽象,所以它可为更高级别的操做系统提供优先权,从而支持实时性。
注意,这种方法和运行多个操做系统的虚拟化方法有一些类似之处。使用这种方法的状况下,超微内核在实时和非实时内核中对硬件进行抽象。这与 hypervisor 从客户(guest)操做系统对裸机进行抽象的方式很类似。
关于超微内核的示例是操做系统的 Adaptive Domain Environment for Operating Systems (ADEOS)。ADEOS 支持多个并发操做系统同步运行。当发生硬件事件后,ADEOS 对链中的每一个操做系统进行查询以肯定使用哪个系统处理事件。
5.3 资源内核(Resource-kernel)
另外一个实时架构是资源内核法。这种方法为内核增长一个模块,为各类资源提供预留(reservation)。这种机制保证了对时分复用(time- multiplexed)系统资源的访问(CPU、网络或磁盘带宽)。这些资源拥有多个预留参数,如循环周期、须要的处理时间(也就是完成处理所需的时间),以及截止时间。
资源内核提供了一组应用程序编程接口(API),容许任务请求这些预留资源。而后资源内核能够合并这些请求,使用任务定义的约束定义一个调度,从而提供肯定的访问(若是没法提供肯定性则返回错误)。经过调度算法,如 Earliest-Deadline-First (EDF),内核能够处理动态的调度负载。
资源内核法实现的一个示例是 CMU 公司的 Linux/RK,它把可移植的资源内核集成到 Linux 中做为一个可加载模块。这种实现演化成商用的 TimeSys Linux/RT 产品。
5.4 标准的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.
http://www.ibm.com/developerworks/cn/linux/l-real-time-linux/#resources
-------------------------------------------------------------------------
本文就到此告一段落,结合本身的实际项目经验,总结了实时操做系统的概念,性能指标,任务调度方法,VxWorks和Linux的实时性对比,以及相应的介绍。供笔者本身学习,也供CSDN各位同窗参考,大部份内容来自网络,不是一篇严谨的论文,若有纰漏还请指出,共同进步。