第四章 内核编译

一.前期准备

1.查看当前系统的内核版本

[root@gzh-cs8 ~]# uname -r
4.18.0-305.3.1.el8.x86_64

2.下载所需要的内核版本

我们通过镜像网站下载所需的内核版本

https://mirrors.edge.kernel.org/pub/linux/kernel

我编译的是5.10.10版本的内核

https://mirrors.edge.kernel.org/pub/linux/kernel/v5.x/linux-5.10.10.tar.gz

我们可以下载下来通过远程连接工具将他传入到centos8里面,也可以通过rz命令上传,也可以通过wget直接下载到centos8中.

这里我们通过远程连接工具上传过去,完成后解压

[root@gzh-cs8 ~]# tar -zxvf linux-5.10.10.tar.gz 
linux-5.10.10/
linux-5.10.10/.clang-format
linux-5.10.10/.cocciconfig
linux-5.10.10/.get_maintainer.ignore
linux-5.10.10/.gitattributes
linux-5.10.10/.gitignore
linux-5.10.10/.mailmap
linux-5.10.10/COPYING
linux-5.10.10/CREDITS
linux-5.10.10/Documentation/
linux-5.10.10/Documentation/.gitignore
......
[root@gzh-cs8 ~]# cd linux-5.10.10
[root@gzh-cs8 linux-5.10.10]# ls
arch     CREDITS        fs       Kbuild   LICENSES     net      security  virt
block    crypto         include  Kconfig  MAINTAINERS  README   sound
certs    Documentation  init     kernel   Makefile     samples  tools
COPYING  drivers        ipc      lib      mm           scripts  usr
[root@gzh-cs8 linux-5.10.10]# ls -a
.              COPYING                 .gitattributes  kernel       net       usr
..             CREDITS                 .gitignore      lib          README    virt
arch           crypto                  include         LICENSES     samples
block          Documentation           init            .mailmap     scripts
certs          drivers                 ipc             MAINTAINERS  security
.clang-format  fs                      Kbuild          Makefile     sound
.cocciconfig   .get_maintainer.ignore  Kconfig         mm           tools

3.修改内核编译config文件

这里补充一下内核编译过程中三个重要的文件Makefile、Kconfig、.config,

不了解内核编译体系,编译修改内核有问题无从下手,自己写的驱动不知道怎么编进内核,不知道怎么配置内核,这些都与这三个文件有管.

  1. 三者的作用:

    简单来说就是去饭店点菜:Kconfig是菜单,Makefile是做法,.config就是你点的菜。

    1. Makefile:一个文本形式的文件,编译源文件的方法。

      作用:用来定义哪些内容作为模块编译,哪些条件编译等。子目录Makefile被顶层Makefile包含。

    2. Kconfig:一个文本形式的文件,内核的配置菜单。

      每个config菜单项都有类型定义: bool布尔类型、 tristate三态(内建、模块、移除)、string字符串、 hex十六进制、integer整型。

      1. Tristate:

        表示该项是否编进内核、编成模块。显示为< > , 假如选择编译成内核模块,则会在.config中生成一个 CONFIG_HELLO_MODULE=m的配置,选择Y就是直接编进内核,会在.config中生成一个 CONFIG_HELLO_MODULE=y的配置项。Tristate后的字符串是make menuconfig时显示的配置项名称。

      2. bool:

        此类型只能选中或不选中,make menuconfig时显示为[ ],即无法配置成模块。

      3. dependon:

        该选项依赖于另一个选项,只有当依赖项被选中时,当前配置项的提示信息才会出现,才能设置当前配置项。

      4. select:

        反向依赖关系,该选项选中时,同时选中select后面定义的那一项。

      5. help:

        帮助信息。

      作用:决定make menuconfig时展示的菜单项(后面会用到)

      目录层次迭代 :

      Kconfig中有类似语句:source "drivers/Kconfig" ,用来包含(或嵌套)新的Kconfig文件,使得各个目录管理各自的配置内容(这些目录在编译目录中都存在),不必把那些配置都写在同一个文件里,方便修改和管理。

      例:

      [root@gzh-cs8 linux-5.10.10]# cat Kconfig 
      # SPDX-License-Identifier: GPL-2.0
      #
      # For a description of the syntax of this configuration file,
      # see Documentation/kbuild/kconfig-language.rst.
      #
      mainmenu "Linux/$(ARCH) $(KERNELVERSION) Kernel Configuration"
      ​
      source "scripts/Kconfig.include"
      ​
      source "init/Kconfig"
      ​
      source "kernel/Kconfig.freezer"
      ​
      source "fs/Kconfig.binfmt"
      ​
      source "mm/Kconfig"
      ​
      source "net/Kconfig"
      ​
      source "drivers/Kconfig"
      ​
      source "fs/Kconfig"
      ​
      source "security/Kconfig"
      ​
      source "crypto/Kconfig"
      ​
      source "lib/Kconfig"
      ​
      source "lib/Kconfig.debug"
      ​
      source "Documentation/Kconfig"
    3. .config:编译内核所依据的配置。

      它是内核编译参考文件,查看里面内容可以知道哪些驱动被编译进内核。

通过上面的简单补充,大概了解了我们为什么要配置.config文件了,就是为了在编译的时候给定要编译的选项,根据需求进行编译.

开始的时候编译目录中是没有.config文件的,我们需要生成.config文件

生成.config文件的方式的两种方法:

  1. make menuconfig

    image-20231008171234803

    这里什么都不用做直接保存然后退出.

  2. 直接修改当前系统内核.config

    我们使用当前系统内核配置文件作为基础进行简单修改的方式配置我们新的内核

    [root@gzh-cs8 linux-5.10.10]# uname -r
    4.18.0-305.3.1.el8.x86_64
    [root@gzh-cs8 linux-5.10.10]# cp /boot/config-4.18.0-305.3.1.el8.x86_64 ./.config
    cp:是否覆盖'./.config'? y

    我们需要修改.config文件

    vim .config

    .config文件中找到CONFIG_SYSTEM_TRUSTED_KEYSCONFIG_DEBUG_INFO_BTF这两行,并将这两行注释。

完成.config修改以后,安装编译所需要的依赖.

4.安装内核编译所需要的依赖

yum install -y ncurses-devel gcc-c++ make openssl-devel bison flex elfutils-libelf-devel bc

5.编译内核

make -j8

-j8参数根据个人自己的计算机进行设置,我的电脑是8核的所以我使用-j8,如果你的电脑是16核的就可以使用-j16,注意-j后面的数字不要超过你电脑的核心数就行了。

编译过程需要很长时间,而且你的centos8的磁盘容量要足够大不然到最后可能编译不成功.

如果编译完成并没有报错的话就可以进行下一步的编译了

[root@gzh-cs8 linux-5.10.10]#make modules
    CALL    scripts/checksyscalls.sh
    CALL    scripts/atomic/check-atomics.sh
    DESCEND objtool
    CHK include/generated/compile.h
    CHK kernel/kheaders data.tar.xz

然后下一步

make modules_install

下一步

[root@gzh-cs8 linux-5.10.10]#make install
sh ./arch/x86/boot/install.sh 5.10.10 arch/x86/boot/bzImage
	System.map "/boot"
[root@gzh-cs8 linux-5.10.10]#

出现上面的输出说明编译成功了

6.使用grubby切换内核

grubby是一个用于更新和显示有关各种体系结构特定的引导程序的配置文件信息的命令行工具。 它主要设计用于安装新内核并需要查找有关当前引导环境的信息的脚本,同时也可以对启动内核的各项信息参数进行修改。grubby已经默认安装在centos8中,如果系统中没有grubby我们也可以通过yum进行安装grubby工具。

yum install -y grubby

查看当前系统默认启动的内核

[root@gzh-cs8 linux-5.10.10]# grubby --default-kernel
/boot/vmlinuz-5.10.10

现在我们的默认内核就是我们的5.10.10

可以通过以下命令查看当前系统有哪些可用的内核

[root@gzh-cs8 linux-5.10.10]# grubby --info=ALL | grep ^kernel
kernel="/boot/vmlinuz-5.10.10"
kernel="/boot/vmlinuz-4.18.0-305.3.1.el8.x86_64"
kernel="/boot/vmlinuz-0-rescue-b73cc1704605433b87c2a93c1dff5a5d"

通过命令grubby --set-default=可以设置你的默认启动内核

[root@gzh-cs8 linux-5.10.10]# grubby --set-default=/boot/vmlinuz-4.18.0-305.3.1.el8.x86_64
The default is /boot/loader/entries/b73cc1704605433b87c2a93c1dff5a5d-4.18.0-305.3.1.el8.x86_64.conf with index 1 and kernel /boot/vmlinuz-4.18.0-305.3.1.el8.x86_64
[root@gzh-cs8 linux-5.10.10]# grubby --default-kernel
/boot/vmlinuz-4.18.0-305.3.1.el8.x86_64

我们重启系统看一下

image-20231008175319303

成功了!!!