编译Linux 2.6.34内核

  • 编译Linux 2.6.34内核已关闭评论
  • 183 次浏览
  • A+
所属分类:linux技术
摘要

《Linux内核设计与实现(第三版)》中所用的内核版本为2.6.34,这个版本太旧了,在高版本系统中编译各种不支持,所以选了Ubuntu 14.04进行编译。

《Linux内核设计与实现(第三版)》中所用的内核版本为2.6.34,这个版本太旧了,在高版本系统中编译各种不支持,所以选了Ubuntu 14.04进行编译。

编译准备

编译环境:Ubuntu 14.04

GCC版本:4.8.4

编译的内核版本:Linux 2.6.34

内核源码下载:https://mirrors.edge.kernel.org/pub/linux/kernel/

编译过程

解压源码linux-2.6.34.tar.gz,进入源码目录执行以下命令:

# make mrproper

# make clean

# make config

# make > /dev/null

编译成功后,源码目录所用空间从443M增至4.9G。

上述命令包含三个阶段:

1)清理

make mrproper,该命令用于清除Linux内核源代码树中生成的文件,通常在编译内核时使用,以确保旧的编译产物被完全清除,以开始一个全新的编译过程,该命令会删除所有的编译生成文件、内核配置文件(.config文件)和各种备份文件,所以几乎只在第一次执行内核编译前才用这条命令。
make clean,该命令则是用于删除大多数的编译生成文件,但是会保留内核的配置文件.config,还有足够的编译支持来建立扩展模块。所以若只想删除前一次编译过程的残留数据,只需执行make clean命令。
make mrproper删除的范围比make clean大,实际上make mrproper在具体执行时第一步就是调用make clean。

2)配置

make config,该命令会逐一遍历所有配置项,要求用户选择yes、no或module,这是一种基于文本的传统配置方式,它会为内核支持的每一个特性向用户提问,如果用户输入“y”,则把该特性编译进内核,如果输入“m”,则把该特性变成以模块,如果输入为“n”,则表示不编译该特性,用户的配置选择结果会存入.config文件。

make config比较繁琐耗时,可以使用make menuconfig或GTK+图形界面下的make gconfig来进行配置选择。

还有两条与配置相关的命令:

make defconfig,生成默认配置。

make oldconfig,检查已有的.config文件和Kconfig文件的规则是否一致,如果一致就什么都不做,否则提示用户哪些源代码中有的选项在.config文件没有,让用户进行选择。Kconfig文件是源码中提供用来配置内核的文件,是各种配置界面(包括make config这样的文本方式)所需要的源文件,内核配置工具读取各个Kconfig文件,生成配置界面供开发人员配置内核,最后生成配置文件.config。当把一个老版本内核源码中已经配置好的.config文件拷贝到一个新版本源码文件夹中继续使用时,应该执行make oldconfig命令,因为新版本内核往往会增加配置项。

3)生成

make,生成内核映像和内核模块。

补充:

make bzImage,只生成内核映像。

make modules,只生成内核模块。

make -jn,开启n个并发编译作业,在多核环境中可以极大加快编译速度。

编译报错

1)报错提示:

gcc: error: elf_x86_64: No such file or directory
gcc: error: unrecognized command line option ‘-m’

解决方法:

这是由于gcc 4.6及以上不再支持linker-style架构,需要将arch/x86/vdso/Makefile中,以VDSO_LDFLAGS_vdso.lds开头所在行的“-m elf_x86_64”替换成“-m64”(注意不是-m 64),将VDSO_LDFLAGS_vdso32.lds开头所在行的“-m elf_i386”替换成“-m32”。

2)报错提示:

drivers/net/igbvf/igbvf.h:129:15: error: duplicate member ‘page’

解决方法:

这是因为高版本GCC对旧定义方式不支持所致,把相关结构体struct igbvf_buffer中最后一个struct page *page注释掉或删掉。

内核安装

# sudo make modules_install

# sudo make install

make modules_install是安装内核模块,安装目录为/lib/modules,这里会生成一个以内核版本号2.6.34命名的子目录,存放各个以.ko为后缀的模块文件。

make install是安装内核映像,安装目录为/boot,本次安装中这里被放入四个文件:vmlinuz-2.6.34,initrd.img-2.6.34,System.map-2.6.34,config-2.6.34

vmlinuz:内核映像文件。

initrd.img:initrd是initial ramdisk的简写,意为初始RAM磁盘,是在系统引导过程中挂载的一个临时根文件系统,initrd绑定到内核,并作为内核引导过程的一部分加载,用来支持两阶段的引导过程。initrd文件中包含了各种可执行程序和驱动程序,它们可以用来挂载真正的根文件系统,然后再将这个临时根文件系统卸载,继而释放内存。但在很多嵌入式系统中initrd就是最终的根文件系统。

System.map:这是一份用于调试内核的符号对照表,可以将内核符号和它们的起始地址对应起来,将内存地址翻译成容易理解的函数名及变量名。

config:从其内容来看,该文件记录了make config中对内核各个配置项的选择。

可以执行make modules_install install将内核模块和内核映像一并安装。

在执行make install时,如果/boot目录下已经存在相同版本的内核,已存在内核会被重命名为vmlinuz-x.x.xx.old。

有些教程中需要手动运行mkinitramfs命令以在/boot下创建initrd文件,但本次测试中运行make install后自动创建了initrd文件。

更新引导

执行命令:

# sudo update-grub

选择内核

方式一:

在系统启动时,按shift键进入GRUB菜单,选择"Advanced Options for Ubuntu",在新菜单页中选择指定版本的内核启动,如"Ubuntu, with Linux 2.6.34"。

方式二:

编辑文件/etc/default/grub,添加配置
GRUB_TIMEOUT_STYLE=menu
再执行update-grub命令更新GRUB配置,系统重启后会自动进入GRUB菜单,再选择指定版本的内核启动。
方式三
直接指定开机启动项,编辑文件/etc/default/grub,将配置GRUB_DEFAULT=0修改如下:
GRUB_DEFAULT="1>4"
其中,1表示在第一个菜单页中选择第2项,也即"Advanced Options for Ubuntu",4表示在第二个菜单页中选择第5项,也即"Ubuntu, with Linux 2.6.34"
再执行updage-grub命令更新GRUB配置,系统重启后会自动按照"1>4"依次选择相应的菜单项。

验证成功

选择2.6.34版本内核重启系统后,执行命令:

# uname -r

可以查看系统当前所用内核的版本。