Linux内核编译初学者指南

Note:这个是早些时候为实验室的团队完成的一个任务,后来略有修改完善,发表一下。

源码获取


Linux内核的官方网站是http://www.kernel.org,访问该网站可以获取内核各个版本的代码。其中网站主页上显示的是当前内核的最新稳定版本。

你可以通过https://www.kernel.org/pub/linux/kernel/来查找任何一个你想要的内核版本,并用wget来下载他。后面都以内核版本3.18作为样例,3.18也是我们项目选定的基础开发版本。

$ wget https://www.kernel.org/pub/linux/kernel/v3.x/linux-3.18.tar.xz

内核是压缩包的形式发布的,其中包含了多种不同的压缩形式,可以用以下命令解压。

$ tar xvf linux-x.y.z.tar.[xz|bz2|gz]

内核编译


  1. 默认的工作目录都是在内核代码的根目录下
  2. 清理源代码

$ make mrproper

删除旧的.o文件、依赖关系、配置文件等。

  1. 生成配置文件

Linux内核支持大量不同的硬件体系结构、外部设备和文件系统等,这就代表了Linux内核是可以高度定制的。你可以把自己需要的功能和设备驱动编译进内核,从而做到最大化的精简和定制。精简内核的好处,除了可以缩减内核文件的大小,缩短编译时间,还可以一定程度的提高性能。

因此,编译内核之前我们需要生成一个叫.config的配置文件,其中列出所有的配置项。比如.config文件里面会有CONFIG_SMP,代表是否支持对称多处理器,它的值可以是y或者n。当y的时候,在内核源代码里面,所有由#ifdef CONFIG_SMP包含的代码都会被编译进内核。一般情况下,对每个配置一般有三种选择:编译进内核;不编译进内核;编译成模块。

首先,如果.config文件已经存在,或者.config文件被修改了可以执行以下命令验证和更新配置:

$ make oldconfig

如上所说,我们需要先生成配置文件之后才能编译内核。关于生成配置文件有以下几个方案。

$ make config

命令行工具,逐个选择所有配置项。很耗费时间,不建议,建议使用后面的图形化工具。

$ make menuconfig

基于ncurse库的图形界面工具。

$ make gconfig

基于gtk+的图形界面工具。

$ make defconfig

基于一个默认的配置,这里就会基于x86_64_defconfig的配置。

执行以上任一命令,你都可以生成一个.config文件。

另外,你还可以拷贝本机当前运行系统的config文件,该文件在/boot/目录下,以config开头的文件。比如你可以执行:

$ cp /boot/config-3.13.0-44-generic .config

$ make oldconfig

特别的,如果我们想要一个能确保可运行,模块最少的配置文件,下面的方法会自动去掉一些从开机到当前没用使用的模块(主要是驱动模块), 所以你可以使用一下你的摄像头, 挂载一下iso文件等以保证需要的模块不会被精简掉,否则使用新内核时会发现不能挂载iso文件,不能使用某些外设等等(当然也可以什么都不管,已经足够保证编译完可运行了)。

$ make localmodconfig

然后出现简单的内核参数选择,可以长按回车键选择默认选项节省时间。最后还用图形界面检查一下是否有自己需要的模块没有选上,也可以忽略。

$ make menuconfig

综上所述,最理想的情况就是大家共用一个研究下来最简的.config文件,既保证了以后不用管配置的事情,也通过最精简获得最优编译时间(而且如果需要另外的模块,之后可以更新这个公共的配置)。

这里有个例子,我们知道Linux虚拟化需要kvm这个模块的支持,以后项目很有可能需要这个功能,但是暂时没用过也不需要这个模块,localmodconfig生成的.config文件中CONFIG_KVM就是没有设置y的。

  1. 加速编译方案

如果以后有多台服务器可研究分布式编译工具distcc。

当前我们使用一个叫ccahe的编译缓存工具,这样在多次编译的时候就可以利用缓存加速了。

安装ccahe并配置缓存大小的上限(默认1G,下面改成了2G,也可以改的更大):

$ sudo apt-get install ccache

$ ln -s /usr/bin/ccache /usr/local/bin/gcc

$ ln -s /usr/bin/ccache /usr/local/bin/g++

$ ln -s /usr/bin/ccache /usr/local/bin/cc

$ ln -s /usr/bin/ccache /usr/local/bin/c++

$ ccache -M 2G

编译的时候可以用下面的命令查看cache的使用和命中情况。

$ ccache -s

  1. 编译和安装内核

使用make命令编译内核,增加多线程编译参数,其中数目一般选择CPU核心数量。这一步比较耗时,可以去看电影了…你也可以用htop命令看看CPU运行状态,无数个100%…

$ make -j4

Tips: 所有费时的命令可使用time计时,这样最后系统就会报告这个任务跑了多久,举上面这个例子,写法就是改成$ time make –j4。

安装模块,模块会被安装在/lib/modules目录下。

$ sudo make modules_install

  • 安装在本机

安装内核并更新启动项。

$ sudo make install

重启。

$ sudo reboot

重启完成后,查看是不是变成了新的内核。

$ uname -r或者$ uname -a

  • 安装在另一台机器

将生成的linux-3.18/.config复制到要替换的系统/boot下,并重命名为config-3.18;

将生成的linux-3.18/arch/x86_64/boot/bzImage复制到要替换系统的/boot下,并重命名为vmlinuz-3.18;

将生成的linux-3.18/System.map复制到要替换系统的/boot下,并重命名为System.map-3.18;

将生成的/lib/modules/3.18.0复制到要替换的系统的/lib/modules下面,文件夹名是3.18;

在要替换系统/lib/modules上执行$ sudo update-initramfs -c -k3.18;

执行$ sudo update-grub2更新内核启动加载项。

Tips:复制文件可以用scp命令,比如:

$ scp -rp System.map  root@192.168.49.164:/boot/System.map-3.18

  1. 编译成deb包安装(推荐)

因为编译成deb包后,不论是本机安装还是换另一台机器安装都更方便,删除也很方便(apt-get –purge remove),所以这个是推荐的方法。

在生成.config文件之后,执行下面的命令(和之前的make一样,会执行很久;需要安装kernel-package才能使用make-kpkg)。

$ sudo apt-get install kernel-package

$ sudo make-kpkg --initrd --append-to-version=-aaa --revision=001.zhoutall -j4 kernel_image kernel_headers

其中-aaa和001.zhoutall都是可以设置的版本信息,该命令完成后就会在上一级目录生成两个.deb包。

linux-headers-3.18.0-aaa-1.zhoutall_amd64.deb

linux-image-3.18.0-aaa-1.zhoutall_amd64.deb

将这两个deb包复制到一个机器上然后执行这样的命令安装。

$ sudo dpkg –i ./*.deb

重启。

$ sudo reboot

重启完成后,查看是不是变成了新的内核。

$ uname -r或者$ uname -a

3 thoughts on “Linux内核编译初学者指南”

  1. 您好,

    能简单的说明一下

    $ ln -s /usr/bin/ccache /usr/local/bin/gcc

    $ ln -s /usr/bin/ccache /usr/local/bin/g++

    $ ln -s /usr/bin/ccache /usr/local/bin/cc

    $ ln -s /usr/bin/ccache /usr/local/bin/c++

    之后,为什么编译就会自动调用ccache呢?是因为ccache会根据文件的后缀自动选择编译器吗?

发表评论

电子邮件地址不会被公开。 必填项已用*标注

Click the right image To submit your comment: