内核裁剪--三星2410

Linux内核模块如何裁剪?

1. Linux内核移植的简介

所谓移植就是把程序代码从一种运行环境转移到另一种运行环境。对于内核移植来说,主要是从一种硬件平台转移到另一种硬件平台上运行。

在一个目标板上Linux内核的移植包括3个层次,分别为体系结构级别的移植、SoC级别的移植和主板级别的移植。

体系结构级别的移植是指在不同体系结构平台上Linux内核的移植,例如,在ARM、MIPS、PPC等不同体系结构上分别都要对每个体系结构进行特定的移植工作。一个新的体系结构出现就需要进行这个层次上的移植。

SoC级别的移植是指在具体的SoC处理器平台上Linux内核的移植,例如,ARM920T IP核的两个处理器S3C2410和AT91RM9200等平台都分别要进行SoC特定的移植工作。

主板级别的移植是指在具体的目标主板上Linux内核的移植,例如,在FS2410目标板上,需要进行主板特定的移植工作。

在这里讨论主板级别的移植,主要是添加开发板初始化和驱动程序的代码。这部分代码大部分是与体系结构相关的,在arch目录下按照不同的体系结构管理。

Linux 2.6内核已经支持S3C2410处理器的多种硬件板,例如,SMDK2410、Simtec-BAST、IPAQ-H1940、Thorcom-VR1000等。我们可以参考SMDK2410参考板来移植开发板的内核。

S3C2410属于片上系统,处理器芯片具备串口、LCD等外围接口的控制器。这样,参考板上的设备驱动程序多数可以直接使用。但并不是所有的外部设备都相同,不同的开发板可以使用不同的SDRAM、Flash、以太网接口芯片等。这就需要根据硬件修改或者开发驱动程序。

例如,串口驱动程序是典型的设备驱动程序之一,这个驱动程序几乎不需要任何改动。然而,如果用2.4内核的配置使用方式,是不能得到串口控制台信息的。在2.6的内核中,串口设备在/dev目录下对应的设备节点为/dev/ttySAC0、/dev/ttySAC1等。所以,再使用过去的串口设备ttyS0,就得不到控制台打印信息了。现在可以很简单地解决这个问题,把内核命令行参数的控制台设置修改为console = ttySAC0,115200。

在内核已经支持S3C2410处理器以后,基本上无须改动代码就可以让内核运行起来。但是,在有些情况下,我们必须针对不同的设备进行驱动级的移植,至少硬件地址和中断号可能会不同。例如,有时需要移植网络芯片和Nand Flash芯片等外设的驱动程序。

Linux内核配置与编译

1.内核配置

编译内核之前要先配置。为了正确、合理地设置内核编译配置选项,从而只编译系统需要的功能的代码,主要有以下4个方面需要考虑。

● 尺寸小。自己定制内核可以使代码尺寸减小,运行将会更快。
● 节省内存。由于内核部分代码永远占用物理内存,定制内核可以使系统拥有更多的可用物理内存。
● 减少漏洞。不需要的功能编译进入内核可能会增加被系统攻击者利用的机会。
● 动态加载模块。根据需要动态地加载模块或者卸载模块,可以节省系统内存。但是,将某种功能编译为模块方式会比编译到
   内核内的方式速度要慢一些。

Linux内核源代码支持20多种体系结构的处理器,还有各种各样的驱动程序。因此,在编译前必须根据特定平台配置内核源代码。Linux内核有上千个配置选项,配置相当复杂。所以,Linux内核源代码组织了一个配置系统。

Linux内核配置系统可以生成内核配置菜单,方便内核配置。配置系统主要包含Makefile、Kconfig和配置工具,可以生成配置接口。配置接口是通过工具来生成的,工具通过Makefile编译执行,选项则是通过各级目录的Kconfig文件定义的。

Linux内核配置命令有make config、make menuconfig和make xconfig,它们分别是字符接口、ncurses光标菜单和X-window图形窗口的配置接口。字符接口配置方式需要回答每一个选项提示,逐个回答内核上千个选项几乎是行不通的;图形窗口的配置接口很好,光标菜单也方便实用。

例如,执行make xconfig,主菜单接口如下图所示。

图1.5 配置内核

2.内核编译

(1)下载内核源码。

从http://www.kernel.org/pub/Linux/kernel/v2.6/Linux-2.6.14.tar.bz2下载Linux-2.6.14内核(或者更高的版本)至/source/kernel目录。解开压缩包,并进入内核源码目录,具体过程如下:

$ tar jxvf Linux-2.6.14.tar.bz2
$ cd Linux-2.6.14

(2)修改内核目录树根下的Makefile,指明交叉编译器:

   $ vim Makefile

找到ARCH和CROSS_COMPILE,修改:

 ARCH = arm
    CROSS_COMPILE = arm-linux-gcc

(3)设置环境变量:

$ export PATH=$PATH:/usr/local/arm/3.3.2/bin

(4)配置内核产生.config文件:

$ cp arch/arm/configs/smdk2410_defconfig .config

(5)输入内核配置命令,进行内核选项的选择,命令如下:

$ make menuconfig

命令执行成功以后,会看到如图1.6所示的界面。其实我们在图1.5中看到过同样功能的界面,那个图也是内核选项配置界面,只不过那个界面在X-window下才能执行。

图1.6 内核选项配置界面

在各级子菜单项中,选择相应的配置时,有3种选择,它们代表的含义分别如下。

● Y:将该功能编译进内核。
● N:不将该功能编译进内核。
● M:将该功能编译成可以在需要时动态插入到内核中的模块。

如果使用的是make xconfig,使用鼠标就可以选择对应的选项。如果使用的是make menuconfig,则需要使用回车键进行选取。

在每一个选项前都有个括号,有的是中括号,有的是尖括号,还有的是圆括号。用空格键选择时可以发现,中括号中要么是空,要么是“”;而尖括号中可以是空、“”和“M”。这表示前者对应的项要么不要,要么编译到内核中;后者则多一样选择,可以编译成模块。而圆括号的内容是要你在所提供的几个选项中选择一项。

在编译内核的过程中,麻烦的事情就是配置这步工作了。初次接触Linux内核的开发者往往弄不清楚该如何选取这些选项。实际上,在配置时,大部分选项可以使用其默认值,只有小部分需要根据用户不同的需要选择。选择的原则是将与内核其他部分关系较远且不经常使用的部分功能代码编译成为可加载模块,这有利于减小内核的长度,减少内核消耗的内存,简化该功能相应的环境改变时对内核的影响;不需要的功能就不要选;与内核关系紧密而且经常使用的部分功能代码直接编译到内核中。

(6)执行下面的命令开始编译:

 $ make zImage

在编译过程中会出现一些错误,可以看到错误发生在/drivers/video/console中。有时是因为我们选择了“VGA text console”选项,去掉这个选项即可。这个选项在“Device Driver”→“Graphics Support”→“console display driver support”下。

总之,这类错误是由于内核配置不当引起的,不需要修改内核源码。

如果按照默认的配置,没有改动的话,编译后系统会在arch/arm/boot目录下生成一个zImage文件,这个文件就是刚刚生成的内核文件。我们需要把它加载到开发板中运行,加以验证。

(7)下载Linux内核。

加载到开发板的方式是通过U-Boot提供的网络功能,直接下载到开发板的内存中。首先把内核复制到tftp服务器的根目录下(见tftp配置文件说明)。在我们的实验中,这个目录在/tftpboot下,所以我们在内核源码目录中直接执行下面命令:

$ cp arch/arm/boot/zImage /tftpboot

启动开发板,在U-Boot界面下输入下面一组命令:

FS2410# printenv (查看当前开发板的环境变量)
FS2410# setenv ipaddr 192.168.1.134 (设置开发板的IP地址为192.168.1.134)
FS2410# setenv serverip 192.168.1.23 (设置开发主机的IP地址为192.168.1.23)
FS2410# setenv bootargs console=ttySAC0,115200 (设置终端为串口1,波特率115200)
FS2410# saveenv (保存环境变量)
FS2410# ping 192.168.1.23 (测试网络是否畅通)

如果网络畅通,执行下面的命令下载内核:

FS2410#tftp 30008000 zImage (把Linux内核下载到开发板内存的30008000地址处)
FS2410#go 30008000 (启动内核)

此时可以在超级终端中观察到内核的启动现象,不过内核在此时还不会成功启动,因为还需要做一些其他的移植工作。

Linux内核结构介绍

Linux内核源代码非常庞大,随着版本的发展不断增加。它使用目录树结构,并且使用Makefile组织配置、编译。关于linux内核的学习,可以参考华清远见《Linux内核修炼培训班》的课程大纲。

初次接触Linux内核,好仔细阅读顶层目录的readme文件,它是Linux内核的概述和编译命令说明。readme的说明侧重于X86等通用的平台,对于某些特殊的体系结构,可能有些特殊的说明。

顶层目录的Makefile是整个内核配置编译的核心文件,负责组织目录树中子目录的编译管理,还可以设置体系结构和版本号等。

内核源码的顶层有许多子目录,分别组织存放各种内核子系统或者文件。具体的目录说明如表1.7所示。

表1.7 Linux内核源码顶层目录说明

arch/体系结构相关的代码,如arch/i386、arch/arm、arch/ppc
crypto常用加密和散列算法(如AES、SHA等),以及一些压缩和CRC校验算法
drivers/各种设备驱动程序,如drivers/char、drivers/block……
documentation/内核文档
fs/文件系统,如fs/ext3、fs/jffs2……
include/内核头文件:include/asm是体系结构相关的头文件,它是include/asm-arm、include/asm-i386等目录的链接;include/linux是Linux内核基本的头文件
init/Linux初始化,如main.c
ipc/进程间通信的代码
kernel/Linux内核核心代码(这部分比较小)
lib/各种库子程序,如zlib、crc32
mm/内存管理代码
net/网络支持代码,主要是网络协议
sound声音驱动的支持
scripts/内部或者外部使用的脚本
usr/用户的代码

Linux内核移植的简介

所谓移植就是把程序代码从一种运行环境转移到另一种运行环境。对于内核移植来说,主要是从一种硬件平台转移到另一种硬件平台上运行。

在一个目标板上Linux内核的移植包括3个层次,分别为体系结构级别的移植、SoC级别的移植和主板级别的移植。

体系结构级别的移植是指在不同体系结构平台上Linux内核的移植,例如,在ARM、MIPS、PPC等不同体系结构上分别都要对每个体系结构进行特定的移植工作。一个新的体系结构出现就需要进行这个层次上的移植。

SoC级别的移植是指在具体的SoC处理器平台上Linux内核的移植,例如,ARM920T IP核的两个处理器S3C2410和AT91RM9200等平台都分别要进行SoC特定的移植工作。

主板级别的移植是指在具体的目标主板上Linux内核的移植,例如,在FS2410目标板上,需要进行主板特定的移植工作。

在这里讨论主板级别的移植,主要是添加开发板初始化和驱动程序的代码。这部分代码大部分是与体系结构相关的,在arch目录下按照不同的体系结构管理。

Linux 2.6内核已经支持S3C2410处理器的多种硬件板,例如,SMDK2410、Simtec-BAST、IPAQ-H1940、Thorcom-VR1000等。我们可以参考SMDK2410参考板来移植开发板的内核。

S3C2410属于片上系统,处理器芯片具备串口、LCD等外围接口的控制器。这样,参考板上的设备驱动程序多数可以直接使用。但并不是所有的外部设备都相同,不同的开发板可以使用不同的SDRAM、Flash、以太网接口芯片等。这就需要根据硬件修改或者开发驱动程序。

例如,串口驱动程序是典型的设备驱动程序之一,这个驱动程序几乎不需要任何改动。然而,如果用2.4内核的配置使用方式,是不能得到串口控制台信息的。在2.6的内核中,串口设备在/dev目录下对应的设备节点为/dev/ttySAC0、/dev/ttySAC1等。所以,再使用过去的串口设备ttyS0,就得不到控制台打印信息了。现在可以很简单地解决这个问题,把内核命令行参数的控制台设置修改为console = ttySAC0,115200。

在内核已经支持S3C2410处理器以后,基本上无须改动代码就可以让内核运行起来。但是,在有些情况下,我们必须针对不同的设备进行驱动级的移植,至少硬件地址和中断号可能会不同。例如,有时需要移植网络芯片和Nand Flash芯片等外设的驱动程序。

Linux内核模块程序结构

Linux内核是Linux操作系统的核心,也是整个Linux功能体现的核心,它是用C语言编写的,符合Posix准。Linux早是由芬兰黑客Linus Torvalds为尝试在英特尔X86架构上提供自由免费的类UNIX操作系统而开发的。该计划开始于1991年,这里有一份Linus Torvalds当时在Usenet新闻组comp.os.minix所登载的帖子,这份著名的帖子标志着Linux计划的正式开始。在计划的早期有一些Minix黑客提供了协助,而今天全球无数程序员正在为该计划无偿提供帮助。

现今Linux是一个一体化内核(Monolithic Kernel)系统,设备驱动程序可以完全访问硬件。Linux内的设备驱动程序可以方便地以模块化(Modularize)的形式设置,并在系统运行期间可直接装载或卸载。

Linux内核主要功能包括进程管理、内存管理、文件管理、设备管理、网络管理等。

  1. 进程管理:进程是在计算机系统中资源分配的小单元。内核负责创建和销毁进程,而且由调度程序采取合适的调度策略,实现进程间的合理且实时的处理器资源的共享。从而内核的进程管理活动实现了多个进程在一个或多个处理器上的抽象。内核还负责实现不同进程间、进程和其他部件之间的通信。

  2. 内存管理:内存是计算机系统中主要的资源。内核使得多个进程安全而合理地共享内存资源,为每个进程在有限的物理资源上建立一个虚拟地址空间。内存管理部分代码可分为硬件无关部分和硬件有关部分:硬件无关部分实现进程和内存之间的地址映射等功能;硬件有关部分实现不同体系结构上的内存管理相关功能并为内存管理提供与硬件无关的虚拟接口。

  3. 文件管理:在Linux系统中的任何一个概念几乎都可以看做一个文件。内核在非结构化的硬件上建立了一个结构化的虚拟文件系统,隐藏了各种硬件的具体细节,从而在整个系统的几乎所有机制中使用文件的抽象。Linux在不同物理介质或虚拟结构上支持数十种文件系统。例如,Linux支持磁盘的标准文件系统ext3和虚拟的特殊文件系统。

  4. 设备管理:Linux系统中几乎每个系统操作终都映射到一个或多个物理设备上。 除了处理器、内存等少数的硬件资源之外,任何一种设备控制操作都由设备特定的驱动代码来进行。内核中必须提供系统中可能要操作的每一种外设的驱动。

  5. 网络管理:内核支持各种网络标准协议和网络设备。网络管理部分可分为网络协议栈和网络设备驱动程序。网络协议栈负责实现每种可能的网络传输协议(TCP/IP协议等);网络设备驱动程序负责与各种网络硬件设备或虚拟设备进行通信。

如何分析Linux内核源码

不少程序员把解读和分析Linux的核心源码作为自己的大兴趣,把修改Linux源码和改造Linux系统作为自己对计算机技术追求的大目标。 不过,由于Linux内核代码的冗长,和Linux内核体系结构的庞杂,所以分析Linux内核也是一个很艰难,很需要毅力的事;在缺乏指导和交流的情况下,尤其如此。那么,到底该如何分析Linux内核源码呢?

要分析Linux内核源码,首先必须找到各个模块的位置,也即要弄懂源码的文件组织形式。虽然对于有经验的高手而言,这个不是很难;但对于很多初级的Linux爱好者,和那些对源码分析很有兴趣但接触不多的人来说,这还是很有必要的。

  1. Linux核心源程序通常都安装在/usr/src/linux下,而且它有一个非常简单的编号约定:任何偶数的核心(的二个数为偶数,例如2.0.30)都是一个稳定地发行的核心,而任何奇数的核心(例如2.1.42)都是一个开发中的核心。

  2. 核心源程序的文件按树形结构进行组织,在源程序树的上层,即目录/usr/src/linux下有这样一些目录和文件:

(1) COPYING: GPL版权申明。对具有GPL版权的源代码改动而形成的程序,或使用GPL工具产生的程序,具有使用GPL发表的义务,如公开源代码;

(2) CREDITS: 光荣榜。对Linux做出过很大贡献的一些人的信息;

(3) MAINTAINERS: 维护人员列表,对当前版本的内核各部分都有谁负责;

(4) Makefile: 第一个Makefile文件。用来组织内核的各模块,记录了个模块间的相互这间的联系和依托关系,编译时使用;仔细阅读各子目录下的Makefile文件对弄清各个文件这间的联系和依托关系很有帮助;

(5) ReadMe: 核心及其编译配置方法简单介绍;

(6) Rules.make: 各种Makefilemake所使用的一些共同规则;

(7) REPORTING-BUGS:有关报告Bug 的一些内容;

● Arch/ :arch子目录包括了所有和体系结构相关的核心代码。它的每一个子目录都代表一种支持的体系结构,例如i386就是关于intel cpu及与之相兼容体系结构的子目录。PC机一般都基于此目录;

● Include/: include子目录包括编译核心所需要的大部分头文件。与平台无关的头文件在 include/linux子目录下,与 intel cpu相关的头文件在include/asm-i386子目录下,而include/scsi目录则是有关scsi设备的头文件目录;

● Init/: 这个目录包含核心的初始化代码(注:不是系统的引导代码),包含两个文件main.c和Version.c,这是研究核心如何工作的好的起点之一。

● Mm/:这个目录包括所有独立于 cpu 体系结构的内存管理代码,如页式存储管理内存的分配和释放等;而和体系结构相关的内存管理代码则位于arch/*/mm/,例如arch/i386/mm/Fault.c;

● Kernel/:主要的核心代码,此目录下的文件实现了大多数linux系统的内核函数,其中重要的文件当属sched.c;同样,和体系结构相关的代码在arch/*/kernel中;

● Drivers/: 放置系统所有的设备驱动程序;每种驱动程序又各占用一个子目录:如,/block 下为块设备驱动程序,比如ide(ide.c)。如果你希望查看所有可能包含文件系统的设备是如何初始化的,你可以看drivers/block/genhd.c中的device_setup()。它不仅初始化硬盘,也初始化网络,因为安装nfs文件系统的时候需要网络;

● Documentation/: 文档目录,没有内核代码,只是一套有用的文档,可惜都是English的,看看应该有用的哦;

● Fs/: 所有的文件系统代码和各种类型的文件操作代码,它的每一个子目录支持一个文件系统, 例如fat和ext2;

● Ipc/: 这个目录包含核心的进程间通讯的代码;

● Lib/: 放置核心的库代码;

● Net/: 核心与网络相关的代码;

● Modules/: 模块文件目录,是个空目录,用于存放编译时产生的模块目标文件;

● Scripts/: 描述文件,脚本,用于对核心的配置;

一般,在每个子目录下,都有一个 Makefile 和一个Readme 文件,仔细阅读这两个文件,对内核源码的理解很有用。

对Linux内核源码的分析,有几个很好的入口点:一个就是系统的引导和初始化,即从机器加电到系统核心的运行;另外一个就是系统调用,系统调用是用户程序或操作调用核心所提供的功能的接口。对于那些对硬件比较熟悉的爱好者,从系统的引导入手进行分析,可能来的容易一些;而从系统调用下口,则可能更合适于那些在dos或Uinx、Linux下有过C编程经验的高手。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

一口Linux

众筹植发

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值