Linux 是当今流行的操作系统之一。由于其源码的开放性,现代操作系统设计的思想和技术能够不断运用于它的新版本中。因此,读懂并修改Linux 内核源代码无疑是学习操作系统设计技术的有效方法。
Linux系统层次结构 :A、GNU C Library (glibc):它提供了连接内核的系统调用接口,还提供了在用户空间应用程序和内核之间进行转换的机制。
B、Linux内核—系统调用接口、进程管理、内存管理、虚拟文件系统、网络堆栈、设备驱动程序、硬件架构的相关代码。
Linux内核源码目录结构:
arch :该子目录包括了所有和体系结构相关的内核代码。它的每一个子目录都代表一种支持的体系结构,例如i386 就是关于intel cpu 及与之相兼容体系结构的子目录。PC机一般都基于此目录。
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()。
lib:放置内核的库代码。
net:内核与网络相关的代码。
ipc:这个目录包含内核的进程间通讯的代码。
fs :所有的文件系统代码和各种类型的文件操作代码,它的每一个子目录支持一个文件系统,例如fat和ext2;
scripts :此目录包含用于编译内核的脚本文件等。
在大多数目录下,都有一个Kconfig文件和一个Makefile文件,这两个文件都是编译时使用的辅助文件;而且,在有的目录下还有readme文件,它是对该目录下的文件的一些说明,同样有利于对内核源码的理解。
在linux 操作系统环境下重新编译内核一般需要以下几个方面: 1 、查找并且下载一份内核源代码 2、配置内核 3、编译内核和模块 4、配置启动文件
下面详细演示一下我的内核编译过程,linux系统是ubuntu12.4 ,要编译的内核版本3.6.6 kernel
ubuntu编译内核步骤:
1
sudoapt-get installlibncurses5 -dev // 如果没有ncurses库,则安装
2、下载内核源代码( 以3.6.6版本为例):linux-3.6.6.tar.bz2文件。下载地址:http://www.kernel.org/
3、 部署内核代码
#su // 输入密码,用户权限改为root 权限。或用sudo命令
#mv linux-3.6.6.tar.bz2 ~ // 把内核代码文件移到主目录。
# cd ~
# tar jxvf linux-3.6.6.tar.bz2 // 解压内核包,生成的内核源代码放在
linux.3.6.6 目录中
# cd linux-3.6.6
4
cp /boot/ config -<Tab> . config // <Tab> 为<Tab> 键
或cp /boot/ config -`uname -r` . config // 使用系统的原配置文件
make menuconfig // 同时生成.config 文件
特别注意:
若在3.6.6内核编译存在错误“ERROR:”__modver_version_show” [drivers/staging/rts5319/rts5319.ko] underfined”。则在make menuconfig 做如下修改:
Device drivers ---
Staging drivers--
RealtekRTS5139 USB card reader support
中把[M] 改为[ ] ,既不编译成模块
进行配置时,大部分选项可以使用其缺省值,只有小部分需要根据用户不同的需要选择。例如,如果硬盘分区采用 ext2文件系统(或 ext3文件系统),则配置项应支持 ext2文件系统(ext3文件系统)。又例如,系统如果配有 SCSI总线及设备,需要在配置中选择 SCSI卡的支持。对每一个配置选项,用户有三种选择,它们分别代表的含义如下:
“<*> ”或“[*]” - 将该功能编译进内核
“[ ] ” - 不将该功能编译进内核
“[M]” - 将该功能编译成可以在需要时动态插入到内核中的模块
将与核心其它部分关系较远且不经常使用的部分功能代码编译成为可加载模块,有利于减小内核的长度,减小内核消耗的内存,简化该功能相应的环境改变时对内核的影响。许多功能都可以这样处理,例如像上面提到的对SCSI卡的支持,等等。
5、如果前面的一切顺利,就可以用make进行编译了
sudo make 或sudomake -j2//这一步花费时间较长,建议去吃饭时做
sudo make modules_install
sudo make install
6 重新启动
sudo reboot // 启动时忽略错误信息提示
7启动后查看内核版本号
uname -r
最后显示3.6.6 说明结果正确