Linux内核移植之刨根问底

2019-07-13 05:36发布

摘要:《ARM嵌入式Linux系统开发详解》第20章Linux内核移植,本章的重点是Linux内核移植,需要考虑硬件平台的差异,涉及较多知识。本节为大家介绍Linux内核移植要点。
第20章  Linux内核移植

软件移植的概念简单地说就是让一套软件在指定的硬件平台上正常运行。移植至少包括了两个不同的硬件或者软件平台。对于应用软件来说,移植主要考虑操作系统的差异,重点在修改系统调用。本章的重点是Linux内核移植,需要考虑硬件平台的差异,涉及较多知识。主要内容如下:

Linux内核移植要点;

内核体系结构框架;

从现有代码移植内核。

20.1  Linux内核移植要点

Linux的代码完全开放以及其良好的结构设计非常适于嵌入式系统。移植Linux系统包括内核、程序库和应用程序,其中最主要的就是内核移植。由于Linux内核的开放性,出现了许多针对嵌入式硬件系统的内核版本,其中著名的包括μcLinux、RT-Linux等。

Linux本身对内存管理(MMU)有很好的支持。因此,在移植的时候首先要考虑到目标硬件平台是否支持MMU。以ARM平台为例,ARM7内核的CPU不支持MMU,无法直接把Linux内核代码移植到ARM7核的硬件平台上。μcLinux是专门针对ARM7这类没有MMU的硬件平台上设计的,它精简了MMU部分代码。本书的目标平台是S3C2440A,该处理器基于ARM9核,支持MMU,可以直接移植Linux 2.6版本的内核代码。

一个硬件平台最主要的是处理器,因此在移植之前需要了解目标平台的处理器。ARM处理器内部采用32位的精简指令架构(RISC),核心结构设计相对简单,有低耗电量的优势,被广泛应用到各种领域。下面介绍一下移植Linux内核对硬件平台需要考虑的几个问题。

1.目标平台

目标平台包括了嵌入式处理器和周围器件,处理器可能整合了一些周围器件,如中断控制器、定时器、总线控制器等。在移植之前需要确定被移植系统对外部设备和总线的支持情况。本书的ARM开发板采用mini2440平台,在S3C2440A外围连接了许多外围设备,包括NOR Flash存储器、NAND Flash存储器、网络接口芯片、USB控制器等。在S3C2440A处理器内部集成了许多常用的控制器以及嵌入式领域常用的总线控制器。对于移植Linux内核来说,操作处理器内部的控制器要比外部的设备容易得多。

2.内存管理单元(MMU)

前面提到过MMU,对于现代计算机来说,MMU负责内存地址保护、虚拟地址和物理地址相互转换工作。在使用MMU的硬件平台上,操作系统通过MMU可以向应用程序提供大于实际物理内存的地址空间,使应用程序获得更高性能。Linux的虚拟内存管理功能就是借助MMU实现的。在移植的时候要考虑目标平台的MMU操作机制,这部分代码是较难理解的,最好能在相似代码基础上修改,降低开发难度。

3.内存映射

嵌入式系统大多都没有配备硬盘,外部存储器只有Flash,并且系统内存也非常有限。内存控制器(Memory Controller)负责内部和外部存储器在处理器地址空间的映射,由于硬件预设的地址不同导致每种平台内存映射的地址也不同。在移植时需要参考硬件的用户手册,得到内存地址的映射方法。

4.存储器

由于嵌入式系统多用Flash存储器作为存储装置。对于文件系统来说,在PC流行的ext2、ext3文件系统在嵌入式系统无法发挥作用。幸好Linux支持许多文件系统,针对Flash存储器可以使用JFFS2文件系统。在移植的时候,不必要的文件系统都可以裁剪掉。
20.2  平台相关代码结构

移植Linux是一项复杂的工作,不仅对目标硬件平台的资源要充分了解,还需要了解Linux内核代码,尤其是与体系结构有关的部分。本节从内核的平台相关代码入手,先介绍内核的工作原理,然后讲解如何移植一个普通的Linux内核到S3C2440A为目标平台的开发板。

在第15章介绍过Linux内核代码结构,与平台相关的代码主要存放在arch目录下,对应的头文件在include目录下。以ARM平台为例,在arch目录下有一个arm子目录,存放所有与ARM体系有关的内核代码。

Linux内核代码目录基本是按照功能块划分的,每个功能块的代码存放在一个目录下。如mm目录存放内存管理单元相关代码;ipc存放了进程间通信相关的代码;kernel存放进程调度相关代码等。

arch目录下每个平台的代码都采用了与内核代码相同的目录结构。以arch/arm目录为例,该目录下mm、lib、kernel、boot目录与内核目录下对应目录的功能相同。此外,还有一些以字符串mach开头的目录,对应不同处理器特定的代码。从arch目录结构可以看出,平台相关的代码都存放到arch目录下,并且使用与内核目录相同的结构。使用SourceInsight工具可以看到许多的同名函数,原因就是内核代码调用的函数是平台相关的,每个平台都有自己的实现方法。对于内核来说,使用相同的名字调用,通过编译选项选择对应平台的代码。

移植内核到新的平台主要任务是修改arch目录下对应体系结构的代码。一般来说,已有的体系结构提供了完整的代码框架,移植只需要按照代码框架编写对应具体硬件平台的代码即可。在编写代码过程中,需要参考硬件的设计包括图纸、引脚连线、操作手册等。

20.3  建立目标平台工程框架

Linux内核2.6版本已经对ARM处理器有很好的支持,并且对三星公司的S3C2440提供一定支持。但是,嵌入式硬件系统的差别很大,移植Linux内核到新的开发板仍然需要修改或者增加针对特定硬件的代码。

Linux内核使用了复杂的工程文件结构,向内核添加新的代码文件需要让内核工程文件知道才行。对于ARM处理器来说,相关的文件都存放在arch/arm目录下:

在arch/arm目录下有许多的子目录和文件。其中以mach字符串开头的子目录存放某种特定的ARM内核处理器相关文件,如mach-s3c2410目录存放S3C2410、S3C2440相关的文件。另外,在mach目录下还会存放针对特定开发板硬件的代码。

boot目录存放了ARM内核通用的启动相关的文件;kernel是与ARM处理器相关的内核代码;mm目录是与ARM处理器相关的内存管理部分代码。以上这些目录的代码一般不需要修改,除非处理器有特殊的地方,只要是基于ARM内核的处理一般都使用相同的内核管理代码。

Kconfig文件是内核使用的选项菜单配置文件,在执行make menuconfig命令的时候会显示出菜单。Kconfig文件描述了菜单项,包括菜单项的属性,与其他菜单项的依赖关系等。通过修改Kconfig文件可以告知内核有关编译的宏,内核顶层的Makefile通过Kconfig文件知道需要编译哪些文件,以及连接关系。

Makefile文件是一个工程文件,每个体系结构的代码中都有该文件。Makefile文件描述了当前体系结构目录下需要编译的文件以及对应的宏的名称。内核顶层Makefile通过Kconfig文件配置的宏,结合Makfile定义的宏关联的代码文件去链接用户编写的代码