分类: LINUX
2008-10-12 20:17:14
众所周知,Linux在嵌入式系统中的应用已经非常普遍。为了进一步促进这方面的应用,在Linux 2.6中,引入了很多非常有利于嵌入式应用的功能。这些新功能包括实时性能的增强、更方便的移植性、对大容量内存的支持、支持微控制器和I/O系统的改进等。
嵌入式计算通常涉及到各种尺寸的计算机,其中包括从小型手持设备(比如手表、照相机)到包含成千上万个节点的分布式系统(比如通信交换机)。嵌入式系统可能简单得只需要一个小的微控制器,也可能使用的是大量的并行处理器和海量的内存。Linux 2.6的改进,则对这一系列需求提供了支持。
响应时间的改进
嵌入式系统通常需要稳定的时间限制。虽然Linux 2.6还不是一个真正的实时操作系统,但说到其改进后的响应能力更加适合于这一领域的需求。
在2.6内核以前,要想让Linux获得更好的响应能力,就需要一些特殊的补丁。通常情况下,需要用户从厂商处购买补丁来改进中断性能和调度反应时间。如今,2.6内核把这些改进加入到了主流的内核当中,因此无需再对其进行特殊的配置。
Linux 2.6提供了一些功能,可以改进整体响应能力。其中两个改变更值得注意,首先现在使用的是抢占式内核,其次使用的调度算法也更加高效。
抢占式内核
和其它大多数通用操作系统一样,当一个进程被系统调用并处于运行状态时,以前版本的Linux是不允许进程进行调度的。这就意味着一旦系统调用中有某个任务正在执行,那么该任务就会控制处理器,直到系统调用结束,而不管其使用处理器时间的长短。这种设计显然要简单得多,但是在很多时候这会导致一些更重要的任务在等待系统调用完成的过程中被耽搁。
现在,内核在一定程度上使用了可抢占的模式。因此,在一些时效性比较强的事件中,Linux 2.6要比2.4具有更好的响应能力。当然了,它实际上并不是一个真正的RTOS,但是与以前的内核相比较,“停顿”的感觉要少得多。在Linux 2.6内核中,代码被设置了抢占点,这就意味着调度程序会中止现在正在运行的进程而来执行优先级更高的进程。在系统调用过程中,Linux 2.6会定时地检查抢占点,以避免不合理的延迟发生。而在检查过程中,调度进程很可能就会中止当前的进程来让另外一个进程运行。
有执行时间限制的软件和虚拟内存请求页面调度是不兼容的,因为这种方法处理页面慢的缺点会破坏程序的响应能力。而2.6内核可以被编译成没有虚拟内存的系统来消除这个问题。当然,这就要求软件设计人员必须考虑要有足够的实内存来运行应用程序。
图1和图2显示了2.4.1内核和2.6内核在平均情况下和最坏情况下任务的响应时间。数据来自通过一台PⅢ 1.0GHz处理器采集的310万个样本。测试使用的是带有超过5个中断的LynuxWorks的实时测试设备。系统处在由持续地磁盘数据传送、网络通信、控制台输入、图像处理和一个定时卡组成的高负载下运行。
高效的调度程序
在2.6版本中,进程调度经过重新编写,去掉了以前版本中效率不高的算法。以前,为了决定下一步要运行哪一个任务,进程调度程序要查看每一个准备好的任务,并且经过计算来决定哪一个任务相对来说更为重要。所有的计算完成之后,得分最高的任务把被选中。因为这种算法中大量的任务需要的时间一般都不相同,一些复杂的多任务应用程序往往得不到及时的调度。
在2.6内核中,调度程序每次不再扫描所有的任务,而是在一个任务变成就绪状态时把其放到一个名为“当前队列”的队列之中。当进程调度程序运行时,它只选择队列中最有利的任务来执行。这样,调度就可以在一个恒定的时间里完成。当任务执行时,它就会得到一个时间段,或在其转到另外一个线程之前得到一段时间的处理器使用权。当它的时间段用完之后,任务就会被移到另外一个名为“过期”的队列中。而在该队列中,任务会根据其优先级进行排序。
从某种意义上讲,所有位于当前队列的任务都把被执行并且都把被移到“过期”队列之中。当这种事情发生时,情况就会有所变化,队列就会被进行切换,原来的“过期”队列成为当前队列,而空的当前队列也就变成了过期队列。由于在新的当前队列中的任务已经被排列好了,调度程序现在也可以使用简单的队列算法,即总是取当前队列的第一个任务进行执行。不管任务是多是少,这个新的过程实际上要比老的过程快得多。
新的同步措施
多进程应用程序有时需要共享一些资源,比如共享内存或设备。为了避免竞争的出现,程序员会使用一个名为互斥的功能来确保同一时刻只有一个任务在使用资源。到目前为止,Linux还是通过一个包含在内核中的系统调用来完成互斥的实现,并由该系统调用来决定一个线程是等待还是继续执行。但当决定继续执行时,这个耗时的系统调用就不需要了。Linux 2.6内核支持所谓的FUSM(Fast User-Space Mutex)。这个新功能会检查用户的空间,查看是否会有等待的情况出现,并且只有在线程需要等待时才进行系统调用。而当等待不需要时,就会避免不必要的系统调用以节约时间。该功能也使用优先级调度,以便在出现竞争时决定哪一个线程可以被执行。
共享内存的改进
嵌入式系统有时也是一个有很多处理器的设备,比如在电信网络或大型存储系统中就是如此。而不论是均衡或是松散连接的多处理器,一般都是共享内存的。均衡多进程的设计是所有的处理器都有对内存有均等使用权,而限制使用内存的决定性因素是进程的效率。Linux 2.6为多程序提供了一种不同的途径,即所谓的NUMA(Non Uniform Memory Access)。这种方法中,内存和处理器是相互连接的,但是对于每一个处理器,一些内存是“关闭”的,而有的内存则是“更远”的。这就意味着当内存竞争出现时,“更近”的处理器对就近的内存有更高的使用权。2.6内核提供了一套功能来定义内存和处理器之间的拓扑关系。调度程序可以利用这些信息来为任务分配本地内存。这减少了内存竞争造成的瓶颈,因而提高了吞吐量。
POSIX线程、信号和计时器
POSIX标准描述的是一套用于创建和管理POSIX线程的功能。这些经过精心定义的系统功能在以前的Linux版本中就可以用了,不过在2.6内核中,它得到了很大的改进。相比较而言,NPTL(Native POSIX Thread Library)的改进更为明显,甚至都已经超过了现在一些补丁中可用的高性能选择方案。
与POSIX线程一起,2.6把POSIX信号和POSIX高精度计时器作为了主流内核的一个组成部分。POSIX信号比以前Linux版本中使用的Unix模式的信号有了很大的改进。新的POSIX信号不能被丢失,并且可以携带信息作为参数。此外,POSIX信号也可以从一个POSIX线程传送至另外一个线程,而不是像Unix信号一样,只能从一个进程至另外一个进程。
嵌入式系统通常要求硬件能够在固定的时间安排下来运行任务。POSIX计时器可以轻松地让任何一个任务都可以周期性地得到预定安排的时间。计时器的时钟可以达到很高的精度,从而可以让软件工程师更加精确地控制任务的调度。
支持通用设计
嵌入式世界里的硬件设计通常都要经过定制,以满足特定的应用程序。因此,设计人员经常需要使用原始的方式来解决设计上的问题。比如,为特定目的制造的主板可能使用不同的IRQ管理器而不是使用类似的设计。为了能在一块新的主板上运行,Linux就要进行更改(迁移)以支持新的硬件。如果操作系统是由独立的组件组成的,那么这种更改应该说是比较简单的,因为只需要更改那些需要更改的代码。在2.6内核中,就引入了一个名为子框架的概念。在新的定义中,各组件被清晰地分开,并且可以独立进行更改或替换,而不会对其它的组件或软件包造成影响,或者影响非常小。
设备、总线和I/O
现在Linux正在变成行业用户的第一选择。2.6内核包含了ALSA(Advanced Linux Sound Architecture),该体系结构可以安全地使用USB和MIDI设备。通过使用ALSA,系统可以同时播放和记录音频。
用于支持视频的Video4Linux系统,在2.6中也焕然一新。虽然其不能向后兼容,但却可用于最新的广播、电视、数码相机和其它的多媒体。
Linux 2.6使用的是USB 2.0,它要比一般的USB快40倍。可以预见,在不久的把来,高速设备把非常普及,而在对USB 2.0支持方面,Linux可以说是一个先行者。
对64位处理器的支持
在一些嵌入式系统中,计算机要提供非常多的资源,比如很大的内存和高吞吐量的多处理器。这些大型系统有数量众多的嵌入式应用程序,比如大规模存储系统和特殊计算引擎。
使用2.6内核,对于那些需要大量内存的嵌入式Linux开发人员就可以选择64位的处理器。Intel安腾64位处理器在以前的Linux版本中就已经被支持,而在新版本中,更是包含了AMD64体系结构,开始提供对AMD Opteron处理器的支持。当然PowerPC也没有被忽略,现在PPC64也已经获得了支持。很显然,Linux社区对于大容量总线、大容量内存计算的创新问题充满了激情。
支持微控制器
现在主流的Linux 2.6内核中,也提供了对微处理控制器的支持。以前,大多数情况下Linux都需要一个包含内存管理的全功能微处理器。然而,在嵌入式市场领域,更简单的微控制器更适于低价和简单的应用。
Linux的微控制项目成为了一个Linux应用于小型系统中非常重要的分支。这个名为uClinux的分支已经受到了小型处理器开发人员的广泛关注。