24.3 核心的编译与安装

将最复杂的核心功能选择完毕后,接下来就是进行这些核心、核心模块的编译了!而编译完成后,当然就是需要使用噜~ 那如何使用新核心呢?就得要考虑 grub 这个玩意儿啦!下面我们就来处理处理:

24.3.1 编译核心与核心模块

核心与核心模块需要先编译起来,而编译的过程其实非常简单,你可以先使用“ make help ”去查阅一下所有可用编译参数, 就会知道有下面这些基本功能:

[[email protected] linux-3.10.89]# make vmlinux  <==未经压缩的核心
[[email protected] linux-3.10.89]# make modules  <==仅核心模块
[[email protected] linux-3.10.89]# make bzImage  <==经压缩过的核心(默认)
[[email protected] linux-3.10.89]# make all      <==进行上述的三个动作

我们常见的在 /boot/ 下面的核心文件,都是经过压缩过的核心文件,因此,上述的动作中比较常用的是 modules 与 bzImage 这两个,其中 bzImage 第三个字母是英文大写的 I 喔!bzImage 可以制作出压缩过后的核心, 也就是一般我们拿来进行系统开机的信息啰!所以,基本上我们会进行的动作是:

[[email protected] linux-3.10.89]# make -j 4 clean    <==先清除暂存盘
[[email protected] linux-3.10.89]# make -j 4 bzImage  <==先编译核心
[[email protected] linux-3.10.89]# make -j 4 modules  <==再编译模块
[[email protected] linux-3.10.89]# make -j 4 clean bzImage modules  <==连续动作!

上述的动作会花费非常长的时间,编译的动作依据你选择的项目以及你主机硬件的性能而不同。此外,为啥要加上 -j 4 呢? 因为鸟哥的系统上面有四个 CPU 核心,这几个核心可以同时进行编译的行为,这样在编译时速度会比较快!如果你的 CPU 核心数 (包括超线程) 有多个, 那这个地方请加上你的可用 CPU 数量吧!

最后制作出来的数据是被放置在 /usr/src/kernels/linux-3.10.89/ 这个目录下,还没有被放到系统的相关路径中喔!在上面的编译过程当中,如果有发生任何错误的话, 很可能是由于核心项目的挑选选择的不好,可能你需要重新以 make menuconfig 再次的检查一下你的相关设置喔! 如果还是无法成功的话,那么或许将原本的核心数据内的 .config 文件,复制到你的核心原始文件目录下, 然后据以修改,应该就可以顺利的编译出你的核心了。最后注意到,下达了 make bzImage 后,最终的结果应该会像这样:

Setup is 16752 Bytes (padded to 16896 Bytes).
System is 4404 kB
CRC 30310acf
Kernel: arch/x86/boot/bzImage is ready  (#1)
[[email protected] linux-3.10.89]# ll arch/x86/boot/bzImage
-rw-r--r--. 1 root root 4526464 Oct 20 09:09 arch/x86/boot/bzImage

可以发现你的核心已经编译好而且放置在 /usr/src/kernels/linux-3.10.89/arch/x86/boot/bzImage 里面啰~那个就是我们的核心文件!最重要就是他啦!我们等一下就会安装到这个文件哩! 然后就是编译模块的部分啰~ make modules 进行完毕后,就等着安装啦! ^_^

24.3.2 实际安装模块

安装模块前有个地方得要特别强调喔!我们知道模块是放置到 /lib/modules/$(uname -r) 目录下的,那如果同一个版本的模块被反复编译后来安装时,会不会产生冲突呢?举例来说,鸟哥这个 3.10.89 的版本第一次编译完成且安装妥当后,发现有个小细节想要重新处理,因此又重新编译过一次,那两个版本一模一样时, 模块放置的目录会一样,此时就会产生冲突了!如何是好?有两个解决方法啦:

  • 先将旧的模块目录更名,然后才安装核心模块到目标目录去;
  • 在 make menuconfig 时,那个 General setup 内的 Local version 修改成新的名称。

鸟哥建议使用第二个方式,因为如此一来,你的模块放置的目录名称就不会相同,这样也就能略过上述的目录同名问题啰! 好,那么如何安装模块到正确的目标目录呢?很简单,同样使用 make 的功能即可:

[[email protected] linux-3.10.89]# make modules_install
[[email protected] linux-3.10.89]# ll /lib/modules/
drwxr-xr-x. 7 root root 4096 Sep  9 01:14 3.10.0-229.11.1.el7.x86_64
drwxr-xr-x. 7 root root 4096 May  4 17:56 3.10.0-229.el7.x86_64
drwxr-xr-x. 3 root root 4096 Oct 20 14:29 3.10.89vbird  # 这就是刚刚装好的核心模块!

看到否,最终会在 /lib/modules 下面创建起你这个核心的相关模块喔!不错吧!模块这样就已经处理妥当啰~ 接下来,就是准备要进行核心的安装了!哈哈!又跟 grub2 有关啰~

24.3.3 开始安装新核心与多重核心菜单 (grub)

现在我们知道核心文件放置在 /usr/src/kernels/linux-3.10.89/arch/x86/boot/bzImage ,但是其实系统核心理论上都是摆在 /boot 下面,且为 vmlinuz 开头的文件名。 此外,我们也晓得一部主机是可以做成多重开机系统的!这样说,应该知道鸟哥想要干嘛了吧? 对啦!我们将同时保留旧版的核心,并且新增新版的核心在我们的主机上面。

此外,与 grub1 不一样, grub2 建议我们不要直接修改配置文件,而是通过让系统自动侦测来处理 grub.cfg 这个配置文件的内容。 所以,在处理核心文件时,可能就得要知道核心文件的命名规则比较好耶!

  • 移动核心到 /boot 且保留旧核心文件

保留旧核心有什么好处呢?最大的好处是可以确保系统能够顺利开机啦!因为核心虽然被编译成功了, 但是并不保证我们刚刚挑选的核心项目完全适合于目前这部主机系统, 可能有某些地方我们忘记选择了,这将导致新核心无法顺利驱动整个主机系统,更差的情况是, 你的主机无法成功开机成功!此时,如果我们保留旧的核心,呵呵!若新核心测试不通过,就用旧核心来启动啊!嘿嘿! 保证比较不会有问题嘛!另外,核心文件通常以 vmlinuz 为开头,接上核心版本为依据的文件名格式,因此可以这样做看看:

[[email protected] linux-3.10.89]# cp arch/x86/boot/bzImage /boot/vmlinuz-3.10.89vbird  <==实际核心
[[email protected] linux-3.10.89]# cp .config /boot/config-3.10.89vbird   <==建议配置文件也复制备份
[[email protected] linux-3.10.89]# chmod a+x /boot/vmlinuz-3.10.89vbird
[[email protected] linux-3.10.89]# cp System.map /boot/System.map-3.10.89vbird
[[email protected] linux-3.10.89]# gzip -c Module.symvers > /boot/symvers-3.10.89vbird.gz
[[email protected] linux-3.10.89]# restorecon -Rv /boot
  • 创建相对应的 Initial Ram Disk (initrd)

还记得 第十九章、开机流程、模块管理与 Loader 谈过的 initramfs 这个玩意儿吧! 由于鸟哥的系统使用 SATA 磁盘,加上刚刚 SATA 磁盘支持的功能并没有直接编译到核心去,所以当然要使用 initramfs 来载入才行! 使用如下的方法来创建 initramfs 吧!记得搭配正确的核心版本喔!

[[email protected] ~]# dracut -v /boot/initramfs-3.10.89vbird.img 3.10.89vbird
  • 编辑开机菜单 (grub)

前面的文件大致上都摆放妥当之后,同时得要依据你的核心版本来处理文件名喔!接下来就直接使用 grub2-mkconfig 来处理你的 grub2 开机菜单设置即可!让我们来处理处理先!

[[email protected] ~]# grub2-mkconfig -o /boot/grub2/grub.cfg
Generating grub configuration file ...
Found linux image: /boot/vmlinuz-3.10.89vbird     # 应该要最早出现!
Found initrd image: /boot/initramfs-3.10.89vbird.img
.....(下面省略).....

因为默认较新版本的核心会放在最前面成为默认的开机菜单项目,所以你得要确认上述的结果中,第一个被发现的核心为你刚刚编译好的核心文件才对喔! 否则等一下开机可能就会出现使用旧核心开机的问题。现在让我们重新开机来测试看看啰!

  • 重新以新核心开机、测试、修改

如果上述的动作都成功后,接下来就是重新开机并选择新核心来启动系统啦!如果系统顺利启动之后,你使用 uname -a 会出现类似下面的数据:

[[email protected] ~]# uname -a
Linux study.centos.vbird 3.10.89vbird #1 SMP Tue Oct 20 09:09:11 CST 2015 x86_64 
x86_64 x86_64 GNU/Linux

包括核心版本与支持的硬件平台都是 OK 的!嘿嘿!那你所编译的核心就是差不多成功的啦! 如果运行一阵子后,你的系统还是稳定的情况下,那就能够将 default 值使用这个新的核心来作为默认开机啰! 这就是核心编译!那你也可以自己处理嵌入式系统的核心编译啰! ^_^

下一节:我们现在知道核心所支持的功能当中,有直接编译到核心内部的,也有使用外挂模块的,外挂模块可以简单的想成就是驱动程序 啦!那么也知道这些核心模块依据不同的版本,被分别放置到 /lib/modules/$(uname -r)/kernel/ 目录中,各个硬件的驱动程序则是放置到 /lib/modules/$(uname -r)/kernel/drivers/ 当中!换个角度再来思考一下,如果刚刚我自己编译的数据中,有些驱动程序忘记编译成为模块了,那是否需要重新进行上述的所有动作? 又如果我想要使用硬件厂商释出的新驱动程序,那该如何是好?