Linux2.4.20的涵义
前两位数字表示版本号,后一位表示发行编号。其中第一位表示主版号,第二个数字表示次版号。奇数的次版号,用来表示开发板内核,如2.5.偶数的次版号,用来表示稳定的内核,如2.4.
Internet上很多被修改的内核都附带有额外的版本信息,如2.4.18-rmk3-hh24,是基于2.4.18版本的Linux内核。
Linux是什么?
Linux指的是Linus Torvolds维护的内核。
Linux还可以用来指运行Linux内核的硬件系统。一个Linux必然包含内核,不过也必然包含一些在Linux内核上运行的其他软件组件。这些软件组件通常是GNU组件的一部分,如C链接库以及一些可执行的工具程序。Linux系统是可以定制的,或者使用既有的发行套件。
Linux还可以指Linux的发行套件。RedHat,Mandrake等都是Linux发行套件。他们有共同的目的:将文件和安装程序打包,让用户能够为特定的目的,将内核及应用程序安装在特定的硬件上。
嵌入式Linux是什么?
一个嵌入式Linux系统只是代表它是一个基于Linux内核的嵌入式系统,这并不意味着该内核使用了任何特定的链接库或用户工具。
一个嵌入式Linux发行套件包括:用来开发嵌入式Linux的平台,各种为了在嵌入式系统中使用而裁剪过的应用软件,或者是这两者。
开发平台包括了各种用来协助开发嵌入式系统的开发工具。这可能包括特殊的源码浏览器,交叉编译器,调试器,项目管理软件,引导映像生成器等等,这些发行套件会被安装在开发主机上。
经过裁剪的嵌入式开发套件提供了一组可以在嵌入式系统中使用的应用程序。这可能包括可以在目标板上使用的特殊链接库,可执行文件以及配置文件。也可能会为目标系统提供一种方法来简化根文件系统的产生。
什么是实时Linux?
Linux加上“实时”这个形容词后,表达的意义就有些不同了。它主要是用来描述系统或其中的组件有固定的响应时间。
嵌入式操作系统有两种时限:严格和宽松。即硬实时操作系统和软实时操作系统。前者要求系统在预定的时间内做出反应,否则会发生灾难性的事件。
开发Linux嵌入式有三种不同的主机/目标板架构:连接式设置,可抽换存储装置设置,独立式设置。实际设置有可能包含多种架构,或甚至会随时间改变,这取决于需求和开发方法。
链接式设置:在这种设置中,主机和目标板会一直被缆线连接在一起。此连接线通常就是一条串行线或一条Ethernet连接。这种设计的主要特色是,目标板与主机之间并未用到实际的硬件存储装置来传送数据。所有的数据都是通过连接传送的。
主机包含了跨平台开发环境,而目标板则包含了引导加载程序,可用的内核和最起码的根文件系统。
链接式设置是最常用的架构。许多嵌入式系统会同时提供Ethernet和RS232的能力。在这样的设置中,Ethernet连接会被用来下载可执行文件,内核,根文件系统,以及其他从主机与目标板间快速数据传送收益的大型条目。而RS232连接则用于调试。
可抽换存储装置设置:在这种设置中,主机和目标板之间没有实际的链接,取而代之的是,先有主机将数据写入存储装置,然后将存储装置连接到目标板。并用该存储装置引导。
与前一种设置相同,主机包含了跨平台开发环境,而目标板则包含了最起码的引导加载程序。其余的组件被存放在可抽换式存储媒体上。先由主机将这些组件写入抽换式存储媒体,然后由目标板上最起码的引导加载程序在启动时加载。
独立式设置:在这种设置中,目标板是一个独立的开发系统,它包含了引导、操作、以及开发额外软件所必须的任何软件。本质上,这种设置就像在使用一个工作站。只不过其底下的硬件不是传统的工作站,而是嵌入式系统本身。
与其他设置不同的是,这种设置不需要任何跨平台的开发环境,因为所有的开发工具都会在固有的环境中执行。而且,目标板与主机之间不需要任何数据传送工作,因为所有必要的存储装置都放在目标板当地。
主机/目标板调试设置的类型
开发者用来连接目标板与主机进行调试的接口基本上有三个类型:串行线,网络接口,特殊的调试硬件。下面简略说一下每种接口的优点和特性。
从主机对目标板进行调试时,最简单的方法就是使用一条串行线。因为串行电路很简单,而且它经常以某种形式出现在嵌入式系统中。然而,使用串行线会遇到两个问题:其一,串行连接的速度会受到限制;其二,如果嵌入式系统只有一个串行接口,或者串行连接是嵌入式系统对外的唯一接口,那么就不可能在对系统进行调试的同时,以终端仿真器跟系统交互。然而,不具备终端交互能力有时并不是问题。
使用网络接口,如Ethernet上的TCP/IP协议,与串行口相比,可以提供宽得多的带宽。此外,目标板与主机可以在相同的物理网络连接上使用多重网络联机。因此,当你对目标板上的应用进行调试时,还可以继续跟目标板进行交互。当你用终端仿真器通过嵌入式系统的串行端口与目标板交互时,还可以通过网络连接进行调试。然而,有网络连接可用就代表存在协议堆栈。因为协议堆栈就存放在Linux内核里,所以网络连接无法对Linux内核进行调试。相对而言,内核的调试通常可以通过串行线来进行。
使用串行连接和网络接口,需要最起码的软件来处理目标板上最原始的I/O硬件。在某些情况下,如将Linux移植到新的目标上或者对内核本身进行调试,就不是这样了。在那些情况下,需要直接能用硬件调试软件的调试接口。目前,如果要直接控制硬件来进行调试,通常会用BDM或JTAG接口。只要将一个特殊的调试器连接到CPU的BDM或JTAG相关管脚,就会完全控制CPU的行为。因此,当遇到新的嵌入式目标板,或者是对目标板上的Linux内核进行调试时,通常会使用JTAG或BDM。
嵌入式Linux系统的一般架构
一般Linux系统的架构如下图:
目标板的硬件必须符合一些要求方能执行Linux系统。第一,Linux需要至少32位的CPU,而且CPU必须配备存储管理单元,(memory management unite ,MMU)。第二,RAM的容量必须满足系统的需要。第三,如果任何开发工作都是在目标板上完成,而且目标板具备适当的调试功能,则需要最起码的I/O能力。如果要实时地进行问题排除,这点也非常重要。最后,内核必须能够通过某些形式的永久性或网络存储装置来加载及(或)存取根文件系统。
硬件的上面就是内核。内核是操作系统的中心组建。使用内核的目的是希望以一致的方式管理硬件,以及为用户软件提供高层抽象层。
为了给应用程序提供他们所需要的功能,内核被大致地分成两个部分:底层接口层,高层抽象层。底层接口层专属于硬件配置,内核运行于底层接口层之上,并以与硬件无关的API(高层抽象层)提供对硬件资源的直接控制。
在底层接口层和高层抽象层之间,内核有时候用到成为“解释组件”的功能来了解如何与特定设备的架构化数据交互。文件系统类型和网络结构协议就是这类结构化数据的主要来源,内核必须知道如何与这些结构化数据交互。
在正常的操作期间,内核至少需要一个具有合适结构的文件系统—根文件系统。内核会从这个文件系统加载它要在系统上执行的第一个应用程序。内核还要靠这个文件系统做更进一步的工作,如加载模块及为每个进程提供工作目录。根文件系统不是存储并且运行在实际的硬件存储装置上,就是在系统启动期间被加载并且运行在RAM上。
系统启动过程
在系统启动过程里,有三个主要软件组件参与其中:引导加载程序,内核,init进程。引导加载程序是系统启动过程中执行的第一个软件,它与目标板的硬件有高度的依存关系。引导加载程序在完成底层硬件的初始化工作后会接着跳到内核的启动程序代码执行。内核一开始的启动程序代码会因架构的不同有很大的差异,而且在为C程序代码设置适合的执行环境之前,它会先为自己进行初始化工作。完成上述工作后,内核会跳到与架构无关的Start-kernel()函数执行,此函数会初始化高层内核功能,安装根文件系统,以及启动init进程。
引导配置的类型
嵌入式Linux系统与它的非Linux同类系统并不相同,嵌入式Linux系统的最大特点是在需要时加载Linux内核及制定的根文件系统。内核的加载及根文件系统的操作受到系统需求(有时还包括系统的开发状态)的影响很大。
嵌入式Linux系统的引导可以有三种配置方式:固态存储媒体,磁盘以及网络。
固态存储媒体:在这种设置中,固态存储装置用来存放最初的引导加载程序,它的配置参数,内核以及根文件系统。尽管嵌入式Linux系统在不同的开发阶段可能会使用其他的引导设置,不过系统完成开发后多半会使用固态存储媒体来存放所有的系统组件。从下图可以看到固态存储装置对所有的系统组件典型的安排方式:
上图并未显示内存地址,因为寻址范围的差异实在太大了。直觉上,你可能认为左边是较低的地址,右边是较高的地址,然而,有时候却刚好相反,引导加载程序位于存储装置的顶端,而不是底部。因此,许多Flash装置会同时提供顶端引导(top-boot)和底部引导(bottom-boot)的配置。Flash装置上引导加载程序所在之处,通常会有保护机制以避免写错内存地址而危害到引导加载程序。
磁盘:内核和根文件系统位于磁盘装置上,最初的内核加载程序不是从磁盘加载第二个内核加载程序,就是从磁盘加载内核本身。然后,磁盘上会有一个被用作根文件系统的文件系统。
网络:在这种设置中,不是根文件系统就是内核与根文件系统会通过网络连接加载。第一种情况是指,内核位于固态存储媒体或磁盘上,通过NFS安装根文件系统。第二种情况是指,只有内核加载程序位于当地的存储媒体上。然后,通过TFTP下载内核,通过NFS安装根文件系统。这种设置适合应用在开发初期,因为它能够让开发者在自己的工作站与目标板间快速地共享数据和软件,而不必编程目标板。相对来说,系统变成产品之后,很少使用这种设置,因为它需要提供服务的服务器。
系统存储器的设计
要想善于利用资源,就必须了解系统内存的设计,以及物理地址空间与内核的虚拟地址空间有何不同。最重要的是,许多硬件外设可以在系统的物理地址空间进行存取,但是限制在虚拟空间中存取或者“完全不可见”。
要熟悉系统的物理和虚拟存储器配置图,物理存储器配置图之所以重要,是因为他可以提供如何设定内核配置以及如何开发定制驱动程序的信息。例如,在设定内核配置期间,可能需要指定Flash装置位于系统何处。在开发期间,也可能会为存储器映射的外设撰写驱动程序。此外,还需要为引导加载程序提供所加载组件的相关信息。因此,最好的做法是,在你进行软件开发之前,先花些时间建立好系统的物理存储器配置图。
启动之后,引导加载程序会立即从根文件系统将内核读进系统的RAM,而且会跳到内核的启动例程执行。从此之后,系统启动过程的其余部分都交给Linux来完成。
一旦Linux运行之后,程序使用的是虚拟地址。与物理存储器配置图相比,虚拟存储器配置图的安排是内核配置设定或设备驱动程序开发的第二个重点。例如,开发设备驱动程序应充分了解哪些信息位于内核空间,哪些位于用户空间,以及必须是使用哪些函数才能正确交互这两个空间的数据。
虚拟存储器的配置之所以重要,是因为他可以帮助你了解应用程序,以及对应用程序进行调试。