最近在学习《操作系统概念》一书,有些实验需要在系统内核中增加一些新的系统调用,由此便产生了修改内核源码并重新编译生成新内核的需求。我的思路是
首先搞定内核编译的流程,确保有个可用的实验环境,在此基础上再按照《操作系统概念》中的方法增加新的系统调用在内核中。
编译环境简单介绍下。
编译用的系统:Fedora core3,对应内核版本为2.6.9-1.677,gcc、make等都是fc3自带的,gcc是3.4.2,make是3.80,x86平台。
最开始下载了个2.6.36的内核源码,分别执行命令【make menuconfig】-【make bzImge】-【make modules】-【modules_install】-【make install】后,编译
生成的内核确实被部署在/boot/下,grub.conf中也增加了相应的启动项,但选中这一内核启动时便提示错误,目前没有搞明白到底是为什么,初步怀疑是新内核和
fc3系统的一些部分不兼容导致,因为目的是为了确保有个编译内核并可用的环境,便没有深究。
drivers/scsi/qla2xxx/qla_os.c: In function `qla2x00_queuecommand': drivers/scsi/qla2xxx/qla_os.c:315: sorry, unimplemented: inlining failed in call to 'qla2x00_callback': function not considered for inlining drivers/scsi/qla2xxx/qla_os.c:269: sorry, unimplemented: called from here drivers/scsi/qla2xxx/qla_os.c:315: sorry, unimplemented: inlining failed in call to 'qla2x00_callback': function not considered for inlining drivers/scsi/qla2xxx/qla_os.c:269: sorry, unimplemented: called from here make[3]: *** [drivers/scsi/qla2xxx/qla_os.o] 错误 1 make[2]: *** [drivers/scsi/qla2xxx] 错误 2 make[1]: *** [drivers/scsi] 错误 2 make: *** [drivers] 错误 2
接下来下载了和fc3内核对应的2.6.9的源码,但在【make modules】时总是不成功,提示信息大概是与scsi相关的一些函数不是inline类型的,把【make bzImage】
生成的内核拷贝到/boot/下,并在grub.conf中增加相应启动项,结果启动菜单中选择新编译的内核启动时提示“unrecognized file format”,仔细检查发现把内核搞
错了,把源码目录linux-2.6.9下生成的vmlinux文件当做内核了,(虽然咨询过朋友说这个也是内核,但很明显文件格式都不一样),正确的应该用linux-2.6.9/arch/i386/
boot/目录下的bzImage,朋友们千万记住了哦。很遗憾的是即便用了正确的内核,发现启动过程中又提示无法加载/lib/modules等,总之依然报错,只是错误发生在启动
过程中了,同样,也没有时间去找原因。
最后,找了个Fedora Core14的系统,对应内核版本为2.6.35.6,gcc版本是4.5.1,make版本是3.82,依然是x86平台。下载与之对应的2.6.35.6的源码,解压至/usr/src下,
便生成了源码目录/usr/src/linux-2.6.35.6。编译内核的过程如下:
[root@fc14]#mv linux-2.6.35.6.tar.gz /usr/src
[root@fc14]#tar -xvzf linux-2.6.35.6.tar.gz
[root@fc14]#cd linux-2.6.35.6
[root@fc14]#make mrproper
[root@fc14]#make menuconfig # 配置内核
[root@fc14]#make dep # 创建内核配置的依赖关系树
[root@fc14]#make clean # 清楚旧版的*.o文件
[root@fc14]#make bzImage # 制作核心文件
[root@fc14]#make modules # 制作相关模块
[root@fc14]#make modules_name # 安装模块到/lib/modules/`uname -r` 目录
[root@fc14]#make install # 安装内核文件到目录/boot
这时切换到/boot/下发现新的内核已经在了,grup.conf中也增加了相应的启动项,重启系统,选择编译后的新内核,成功启动。
下面对这个过程中自己所理解的一些东西进行描述,如有不当之处,欢迎各位指正。
make mrproper---这个命令用来确保源代码目录下没有不正确的目标.o文件以及文件的互相依赖,同时,还会删除源码目录下
的.config文件。.config文件中保存的是内核配置,新下载的源码包中是没有的,而且也不会存在不正确的.o文件等,因此这一步
对新下载的源码包可以省略。当你要对现有系统升级内核,而不修改内核的相关配置时,可以将当前系统的.config文件
(如果能找到的话O(∩_∩)O)拷贝到源码目录下使用。这一命令建议都执行一下,确保内核源码包中的内容是干净的。
有人说这一步后要确保/usr/include/目录下的asm、linux、scsi等连接是指向要升级的内核源码的,我没明白是为什么,也没有
做这一步。
make menuconfig---这是最常用来配合内核选项的命令,是基于文本选项的配置界面,字符终端下推荐使用。网上有人说要使用
这个命令必须安装ncurses-dev和tk4-dev库,因为我的机器上默认就能用,所以也没有验证这一点。当然还有基于文本的【make config】
和基于图形窗口的【make xconfig】(xwindows下推荐使用)。另外,【make oldconfig】据说是如果只想在原来内核配置的基础上
修改一些小地方可以使用,应该和上面说的“升级现有内核”但不修改配置等同,没有验证。
配置完成后保存退出,也会生成.config文件。
make dep---此命令用啦读取配置过程生成的.config配置文件,并创建对应于配置的依赖关系树,从而确定哪些需要编译,哪些不需要
编译。不过大家都说这条命令在2.6及以后的内核编译中都不再需要,如果执行就会出现“***Warning: make de is unnecessary now”
的提示。我编译2.6.9和2.6.35.6的内核时都执行过,确实是这个提示。
make bzImage----这个就是编译内核的命令了。此外还有【make zImage】,但zImage是用gzip压缩的,适合存储在软盘上。bzImage
是更大的超过软盘空间限制的压缩内核,我这里用的是bzImage。这个命令在目录/usr/src/linux-2.6.35.6/arch/i386/boot/下创建bzImage
文件,当然,这个文件是一个链接,指向../../x86/boot/bzImage,也就是真正的内核文件。
make modules---这个命令用来编译以生成相应的内核模块。
make modules_install---这个命令会在/lib/modules/目录下生成相应的2.6.35.6目录,该目录下即为编译过的内核模块。
/lib/modules/x.y.z是模块在系统中的标准目录。
make install---安装内核。这一命令会将生成的/usr/src/System.map、/usr/src/linux-2..35.6/arch/i386/boot/bzImage拷贝
到/boot/下,并修改grub.conf启动菜单配置,实际上就是将编译出的内核安装到当前系统中。
至此,编译内核过程完成,而且已经安装到当前系统,重启系统发现启动项中多了新内核的启动项,选择之,启动即可。
【make modules】 以及【make modules_install】命令有人说不必要,目前为止我还没搞清楚它和编译内核的关系,但
感觉其生成的内核模块(即*.ko)文件在内核运行过程中若需要加载时是需要的,所以建议还是一起做了。
补充:
额外模块的安装。----------------这是从网上摘抄的,没有试验过。
比如我现在给机器加了个Intel 3945的无线网卡,那么要使其能正常使用,就要安装其对应的驱动模块。
tar -xvzf ipw3945-1.2.2.gz
cd ipw3945-1.2.2
将编译出来的模块文件ipw3945.ko一道核心目录,并更新模块的依赖属性:
cp ipw3945.ko /lib/modules/`uname -r`/kernel/drivers/net
cd /lib/modules/`uname -r`
depmod -a
开机自动加载模块:
cd /etc/sysconfig/modules
echo "modprobe ipw3945" >> my.modules
chmod 755 my.modules
重启后查看模块是否加载:
lsmod |grep ipw3945
ps:每次更新kernel后需要重新编译一次额外添加的模块。
核心模块管理:
lsmod :列出所有模块
modinfo:查看模块信息
modprobe:-c 查看配置文件
-l 列出所有模块
-r 移除模块
insmod:插入模块
rmmod:删除模块