实时和Linux 第三部分: 子内核和基准

本文译者

康华:计算机硕士,主要从事Linux操作系统内核、Linux技术标准、计算机安全、软件测试等领域的研究与开发工作,现就职于信息产业部软件与集成电路促进中心所属的MII-HP Linux软件实验室。如果需要可以联系通过kanghua151@msn.com联系他。

 

 

注明:棕色写的内容为译者注。

如果有意义不明之处请参见原文

 

 

Kevin Dankwardt

在前两篇文章中(请看实时和Linux的第一部分实时和Linux的第二部分:抢占式内核)我们讨论了实时的基本概念和提高内核实时性的途径。这次我们将介绍两种改造普通内核为实时内核的例子,其中要引入一种介于硬件和普通Linux之间独立的小型实时性内核。我们同时还要借助基准(一组测量程序)来对桌面/服务器使用的Linux内核与改造过的内核做比较。

我们不深入讨论LynxWorksOnCore系统提供的与Linux兼容的优先级(proprietary)内核。LynuxWorks提供了一个兼容Linux API的实时内核;而OnCore系统则提供了一个实时微内核,并利用各种各样的方法提供了Linux所具有的功能。通过这些方法,用户可以在微内核之上运行具有实时性的Linux内核。

本文所讨论的方法局限于单CPU的实时性。如果系统使用多个CPU,那么可能需要其它新的解决方法。比如,这时不要在一个已经有其它实时进程等待的CPU上调用新进程,如此才可避免内核抢占。另外,CPU系统还可能将中断报告给一个特定的CPU,然后中断处理程序自另一个CPU上结束,从而避免了延迟中断响应的问题。

我们所谈到的所有的Linux实时措施,通常都不合适多CPU系统——比如,RTAI系统它必须使用额外的功能才满足多CPU系统——但是我们针对的是嵌入系统的开发者,多数嵌入Linux设备都只有唯一的通用CPU

什么是实时子内核?

在典型的实时系统中有许多任务必须具有确定性,具有实时性。另外对硬件中断的响应往往也必须具有确定性。为了获得这些要求有一个巧妙的办法:建立一个即可以提供上述服务(有确定性)又能运行标准Linux内核的小型操作系统内核,这样以来可以满足实时要求的同时还能提供所有标准Linux的功能。

这些实时子内核都实现了几组API函数分别为任务、中断处理程序、与Linux进程通讯等服务。当子内核任务运行或当子内核处理中断时,Linux将被挂起等待。注意,这里Linux是不允许禁止中断的(标准Linux在处理中断时,一般是要禁止同类或所有中断的)。另外要明确:这些子内核不是完整的操作系统内核,它们没有足够的设备驱动程序,也没有提供其它的库,因此它们仅仅作为Linux系统的一个插件,而并非独立的操作系统。

但是这些子内核随软件版本的更新换代,更多更强的功能被不断加入,其结构也变得越来越复杂。虽然如此子内核的最大魅力还是在于:它们不影响使用标准Linux的任何功能,它们仅仅处理应用程序中对实时性有要求的那一部分任务。

从某种角度看,Linux在这里是子内核OS中的一个任务,而且是个优先级最低的任务,或是个空任务(idle)。

1描述了子内核和Linux之间的关系。

 

子内核和Linux协同工作需要作三件事情:

1)对Linux内核打补丁给其加入一些钩子(hook),便于填加功能。

2)修改中断处理程序。

3)利用可装载模块提供API和所需功能。

子内核为实时任务提供了一组API。这些API类似于POSIX线程和其它POSIX函数,另外也实现一些新函数。使用子内核意味着:虽然子内核API独立实现而且和传统LinuxAPI可能有少许不同,但是Linux开发者可以像使用熟悉的Linux API一样利用子内核的API创建实时任务。

内核原代码中的中断处理程序需要修改。比如修改禁止中断的内核代码,使得在内核源代码和驱动程序代码重新编译后,该代码实际上失去禁止中断的作用。一定要注意这个变化,因为如果疏忽,比如,让一个驱动程序脱离修改过的头文件在别处被编译,那么它可能会禁止中断并且会破坏实时性。另外一些非标准代码,比如,简单的内联一个中断禁止汇编语句指令就有可能破坏实时性。好在,实际操作中这些情况并不常见,而且也可以避免。这点再次印证了一个道理——不存在绝对的实时方法。

RTLinux RTAI

使用子内核的两个最著名的系统是RTLinuxRTAT。这两个系统都是为硬实时要求设计,其中用到的技术决非仅仅是抢占式内核(但也有些地方比抢占内核要弱)。在实际应用中,实时系统为开发者提供了很大便利。RTLinuxRTAI都提供了许多额外的、实时相关函数。比如RTAI就提供了一恒时(rate-monotonic)调度方法和early-deadline-first 调度方法。当然同时也保留了传统的优先级调度方法。

子内核提供了POSIX规范指定的函数和一些专有函数,同时还提供了创建任务,禁止/激活中断、同步和通讯的API接口。当使用RTLinuxRTAI时开发者可以使用POSIX函数和上述的新建API 

RTLinuxRTAI都支持用户空间进程和内核协同工作。因为Linux实时应用程序显然希望能够使用Liunx的功能。所以RTLinux支持用户空间进程调用信号处理程序,而且也同时支持在内核空间和用户空间读写FIFO和共享内存。RTAI也不例外地提供了FIFO、共享内存和一个完整的硬实时机制——LXRT,该机制可以在用户空间中使用。

但是既是使用这些机制也并不能使得Linux内核实时化,一个用户空间进程仍然必须避免使用系统调用,因为系统调用有可能在内核中堵塞。另外无论是RTLinux还是RTAI都无法和一个抢占式内核一同工作。因为这两种方法是正交的(orthogonal),也许今后他们可能融合。特别是现在Love的补丁已经进入2.5版本的标准内核,而且很有可能在2.6稳定版中发布。

选择时要考虑的问题

开发者需要实时性时,可以选择RTlinuxRTAILove的抢占式内核和TimeSys的抢占内核。选择的标准众多,我们这里简要地说明多数开发者最关心的几个问题。

l         哪一种是开源的,是由独立的自由开发者维护的? RTAILove

l         哪一种软件的技术具有专利?RTLinux

l         哪一种是2.5内核树的一部分 Love

l         哪些除了抢占式内核外还有其它实时功能?TimeSys,RTAIRTLinux

l         哪些可以继续免费下载?RTAILove(我以经验判断)

l         哪些能控制中断,并且有可能提供接近机器速度的(near-machine-level)的响应速度? RTLinuxRTAI

内核是否对不同处理器都有效

注意这些实时方法对于可以运行Linux的所有处理器都有效;如果要移植到新处理器,就需要进行一些额外的改造。但是不要担心,我们上面提到的4种系统或补丁的研发行为都是相当活跃的,我可以打宝票对新型CPU的支持指日可待。

Love的抢占内核目前只可用于x86系列的处理器,但是借助MontaVista的支持很有可能被移植到MontaVista支持的绝大多数CPU上——如果不是全部的话,它们包括PowerPC, ARM, MIPS, SuperH等等;TimeSys内核目前可用于PowerPC, ARM, SuperH Pentium等处理器。RTlinux可用于x86PowerPCRTAI可用于x86PowerPC

基准

你可以从网上(请看资源筐中的K Computing基准)下载基准程序。我们使用的所有基准程序都是运行在456MhzCeleron体系结构上的,但对于其它,如x86CPU,也有类似的运行结果。目前对于其它类型的CPU还没有相应的基准程序。

我们将测量这几种内核:红帽子7.2版本的内核,该内核的基础是2.4.7版本的Linux内核;TimeSys Linux3.0内核,它的基础是2.4.7版本Linux内核;另外还要测量打上Robert Love补丁和MontaVista的抢占补丁的内核。我们将简称这些内核为红帽子、TimeSysLove。我们会分别用基准程序测量RTAIRTLinux内核的。

基准程序包括测量nanosleep()调用的响应速度。睡眠时间的精确度对内核是否能可靠的服务用户空间的实时进程至关重要。Linux nanosleep()函数允许请求纳秒级的睡眠。我们基准程序将请求50豪秒睡眠,有趣的是,请求nanosleep()睡眠N豪秒,实际却肯定要睡眠N+10毫秒。所以我们测量实际睡眠时间与预想的60豪秒的接近程度。另外,要注意当请求睡眠小于两毫秒时,nanosleep()在内核中进行忙循环。所以忙等待将无法象真睡眠一样模拟中断响应时间。

基准程序一共有1000个例子,后988个有图形显示。前两个没有使用图形显示,是为了避免冷缓存造成的缓存减速(cache slowdowns as a result of a cold cache)。基准程序通过mlockall()被锁定到内存并且通过sched_set_scheduler()sched_get_priority_max()给予其最高的FIFO优先级。

基准的核心是:

 t1 = get_cycles();

 nanosleep(fifty_ms, NULL);

 t2 = get_cycles();

 jitter[i] = t2 - t1;

get_cycles()函数是以机器无关的方法读取CPU的周期记数cycle counter的。在0x86机器上需要读时间戳计数(TSC),TSCCPU频率增加。所以如果在500MHZCPU上,TSC每秒增加500000000

CPU的频率可以在/proc/cpuinfo 中获得。我们每10个指令周期读一次TSC,然后就可以精确比较我们的定时时间和实际时间的差值了。

和我们希望的睡眠时间50+10毫秒的误差,计算如下:

 diff = (jitter/KHz) - 10 - 50;

 

下面五个Benno Senoner的基准程序用来进行压力测试,它们是响应速度测试的一部分,这些对系统的压力测试分别是:拷贝磁盘文件、读磁盘文件、写磁盘文件、读/proc文件系统和执行X11性能测试。 2-6给出了三种内核装入上述任务时的负载情况。

2拷贝磁盘文件

3读磁盘文件

4写磁盘文件

5 /proc文件系统

6 执行X11性能测试

可以看出,抢占内核能够提供更好的响应速度,而且因为抢占内核在不需要改变API的情况下能被应用程序使用。所以它们显然对Linux开发者最有吸引力。

由于红帽子内核响应速度明显低于LoveTimeSys的内核,所以我们进一步显示对比LoveTimeSys的抢占内核。结果请看图7-11

7 LoveTimeSys :拷贝磁盘文件

8 LoveTimeSys :读磁盘文件

9 LoveTimeSys :写磁盘文件

10 LoveTimeSys :读/proc文件系统

11 LoveTimeSys :执行X11性能测试

 

RTLinux RTAI 基准

我们希望RTAIRTLinux能在高负载的情况下提供强健的性能。通过我们基准程序的测试,它们的确能符合我们的要求。但是我们仍然必须防范一些不当操作,要记住以下原则 :对内存分配这样的任务执行期间不要堵塞,不要使用没有禁止中断的驱动程序,要避免耗时的优先级反转(优先级反转是指一个任务等待比它优先级低的任务释放资源而被阻塞,如果这时 
有中等优先级的就绪任务,阻塞会进一步恶化。优先级继承技术可用来解决优先级反转问题)

为了测量RTAIRTLinux基准,我们创建了周期运行的任务并测量实际执行时刻和希望周期率的间隔,RTLinuxRTAI的最坏情况时差为30毫秒或更短。我们的基准程序可以免费下载(请看K Computing 基准资源框)

 

                                             资源

 

 

关于作者: Kevin Dankwardt K Computing 公司的创始人和CEO ,该公司是一家硅谷的培训和咨询公司 。特别要强调的是,该公司在全球范围内发展和推广嵌入和实时Linux培训

优先级继承可用来解决优先级反转问题。当优先级反转发生时,优先级较低的 
任务被暂时地提高它的优先级,使得该任务能尽快执行,释放出优先级较高的 
任务所需要的资源

 

译者: LinuxSaga——我们是一群Linux爱好者,成为Linux骇客是我们的理想。

 

       我们的网站: www.linuxsports.com