linux实时性分析与改进

2019-07-13 06:10发布

1 引言 嵌入式Linux(Embedded Linux)是指对桌面型 Linux经过小型化裁剪后,能够固化在容量只有几百K 字节或几兆字节的存储器芯片或单片机中,应用于特定嵌入式场合、为嵌入式应用程序提供操作系统服务的专用Linux 操作系统。 实时性”是指计算机系统在确定的时间内完成规定的功能,并能够对外部的异步事件做出正确响应的能力。实时性又可分为软实时(Soft Real-time)和硬实时(HardReal-time)两种。软实时是指统计意义上的实时,一般整体吞吐量大或整体响应速度快,但不能保证特定的任务在指定的时间内完成。硬实时则是指时间要求必须被严格保证的实时,对任务的执行时限的要求非常严格,无论在什么情况下,任务的执行实现必须得到绝对保证,否则将产生灾难性后果。这才是真正意义上的实时 [1]。Linux有很好的“平均”性能,具有一定的软实时性,但不是硬实时的操作系统,因此要使Linux成为真正的实时操作系统必须对其作一些相关的改造。 2标准Linux内核制约实时性的因素 实时系统主要考虑任务的按时完成、尽量减少进程运行时的不可预测性等,而Linux 一开始并不是针对要求实时性非常强的嵌入式领域开发的,因此其实时性比较弱。(1)过长的中断禁止时间、(2)非抢占式的内核以及(3)耗尽式的、机会均等的进程调度策略是Linux 实时性不强的几个主要原因。 2.1不确定的任务切换时间 确定的任务切换时间和中断延迟时间是实时操作系统区别于普通操作系统的一个重要标志,是衡量实时操作系统的实时性的重要标准。 任务切换时间包括保存目前任务的时间,新任务调入系统的时间和操作系统选择下一个任务的调度时间,其中任务调度时间是决定任务切换时间长短的主要因素。而影响这一时间的因素主要是任务调度策略和被调度的任务数。调度策略越简单,被调度的任务总数越少,调度时间就越短。对一个实时性能较强的操作系统而言,系统必须规定不同进程的优先级,把不同类型的进程分成不同的队列,并把优先级作为唯一的进程调度标准,尽量缩短任务调度时间。 Linux 在内核1.3 版本之后加进了POSIX 实时扩展部分,引进了实时进程概念,允许将一个进程的属性确定为实时进程。Linux从调度策略上区分实时进程和普通进程,实时进程先于普通进程运行,并采用不同的调度策略。对实时进程,Linux 采用两种调度策略,即先来先服务调度(SCHED_FIFO)和时间片轮转调度(SCHED_RR)。SCHED_RR任务最先被调度并拥有时间片,一旦时间片用完就被移动到优先级队列的队尾,并允许同一优先级的其他任务运行。如果同一优先级没有其他任务,该任务将继续运行下一个时间片。SCHED_FIFO 是运行直至阻塞的策略。其任务按优先级调度,一旦开始就一直运行到结束或者阻塞在某种资源上。它们不像SCHED_RR 任务那样共享处理器。 2.2中断延迟时间 上面我们提到,中断延迟时间也是实时操作系统区别于普通操作系统的一个重要标志。 中断延迟时间是指系统确认中断开始直到执行中断服务程序的第一条指令为止整个处理过程所需要的时间。操作系统的中断延迟时间由下列三个因素决定: (1)处理器硬件电路的延迟时间,通常这个时间可以忽略。 (2)操作系统处理中断并将控制权转移给相关处理程序所需要的时间。 (3)操作系统的中断禁止时间。 测试表明,产生中断延迟的原因除了处理器响应时间外,更重要的是操作系统的一些操作会大大增加中断被延迟的时间。在操作系统运行过程中,存在着一些关键的操作。这些操作在执行时,操作系统会禁止在其间插入任何中断。例如:ISR在执行时候,外部中断是被禁止的。因此如果一个中断请求在操作系统禁止中断的这段时间里产生,那么对它的处理就会始终保持在挂起状态,直到操作系统重新允许中断插入。会有这样的一种情况出现,即使Linux本身的中断响应时间非常短,如果在一个ISR执行期间某个外设也产生了一个中断信号,因为正在执行的ISR运行时间的不确定性和不可抢占性,也会产生Linux的中断延时的不可预测性。 2.3共享资源的互斥访问 Linux操作系统一般采用信号量机制来解决共享资源的互斥访问问题。如果任务调度采用基于优先级的方式,则传统的信号量机制在系统运行时很容易造成优先级倒置问题,即当一个高优先级任务通过信号量机制访问共享资源时,该信号量已被一低优先级任务占有,而这个低优先级任务在访问共享资源时可能又被其它一些中等优先级的任务抢先,因此造成高优先级任务被许多具有较低优先级的任务阻塞,实时性难以得到保证。 3嵌入式Linux的实时化方案 3.1实时进程的调度 为实现Linux 的实时性,可以将内核中的进程调度遵循POSIX 标准进行改写,在Linux 内核限定的范围内,通过对源代码的修改,尽可能地扩充其实时性,使Linux 变成一个真正的实时操作系统。 这需要精心选择改动部分,一般要完全重新编写一个由优先级驱动的实时调度器,替换原有内核中的进程调度器。对于不同的进程,采用不同的调度策略,例如对实时进程实现抢占式的调度。我们可以找出Linux 所有系统调用中的关键代码段,在执行关键代码段时,设置标志位来决定是否允许进行任务切换,并且可以在内核函数中增加抢占点的个数,在保证其操作互斥性的同时,增强内核的可抢占性,实现一种可抢占的内核。对于采用抢占式核心程序设计,系统可能出现的优先级反转问题,可以采用优先级继承或优先级天花板的方式来解决。这种方案的最大优点在于系统执行效率高,可以获得更好的性能。但是,它要求开发人员精通Linux 内核,并且开发难度大、开发周期长。 3.2时钟粒度的细化 通过将周期性的时钟中断改为非周期性的时钟中断这种简单而且代价较小的方式,从而达到细化时钟粒度的目标。提供与标准Linux核心时钟并行运行的一个具有精密刻度的实时核心时钟处理系统,与原Linux 核心时钟区别开来。不但提高了系统的稳定性和效率,而且独立的实时核心时钟易于维护改进。所有实时定时器都是由堆的数据结构组织和管理的。在时钟中断的处理函数do_timer_interupt()(arch/386/kernel/Time.c)中,调用相应的函数处理实时定时器队列。具体过程为判断堆顶定时器是否到期,如果到期,则调用其服务函数。 3.3中断的实时性改进 软中断运行的时机之一就是在中断服务的末尾。Linux中断服务函数中进行软中断处理的代码如下[4] : asmlinkage unsigned int do_IRQ(struct pt_regs regs) { …… if (softirq_active(cpu) &softirq_mask(cpu)) do_softirq(); return 1; } 其中do_IRQ()是Linux中断服务函数,此函数针对特定的中断运行相应的上半部分。函数do_softirq()是软中断处理函数。在do_IRQ()处理完上半部分时,如果有等待的软中断需要处理,那么就会调用do_softirq(),处理待运行的软中断。如果中断上半部分需要下半部分被处理,那么下半部分也会在do_softirq()中被运行。我们知道,Linux之所以将中断分为两个部分,就是为了将不着急的事务推迟处理从而减少中断服务时间。现在,如果do_IRQ()中软中断的处理时间过长,那么do_IRQ()的处理时间也会相应变长,从而增加了中断服务时间。为了进一步减少中断服务时间,我们可以考虑在中断处理函数中对中断进行区别对待。对于不频繁的外部中断,如键盘、时钟等,保留软中断处理。而当系统需要处理某些频率较高的外部中断时,我们可以考虑绕过软中断的处理,只处理上半部分。由于软中断本身不是急需处理的,并且还可以在进程调度之前和系统调用结束时运行,因此,这里将它去掉对系统性能的影响不大。 4结论 由于Linux本身基于通用目的操作系统的设计,其实时性能并不是很强。但通过一定的改进增强其实时性能,就可以用于实时的应用场合。本文在分析了标准Linux实时性的基础上,并就实时进程的调度、中断、时钟三个方面提出了一些改进的方法,以进一步提高Linux操作系统的实时性能。