Linux内核编译与安装

admin 2023年04月30日 1,087次浏览

我们通常所说的 Linux 其实指的是 Linux 内核(kernel),而 Redhat、Debian、Ubuntu 这些称之为发行版。kernel 是操作系统的最底层,负责整个硬件的驱动,以及提供各种系统所需的核心功能,包括防火墙机制、是否支持 LVM 或 Quota 等文件系统等等。在主机开机的时候,其实就是利用开机管理程序加载这个内核文件,来检测硬件,在内核加载适当的驱动程序后,系统才能够顺利的运行

对于内核的编译安装,一般用于特殊功能的需求,否则建议使用在线更新,而非手动编译安装

1、准备工作

1.1、内核简介

  • kernel

    kernel 只是系统上面的一个文件, 这个文件包含了驱动主机各种硬件的检测程序与驱动模块,这个文件的路径通常为 /boot/vmlinuz-xxx

  • 核心模块 (kernel module)的作用

    既然内核已经包含了硬件检测和驱动模块,那么我们为啥还需要核心模块呢,这是因为,由于硬件的更新换代速度特别快,老的内核无法支持新硬件的运行,但是又不能仅仅为了一个小硬件去重新编译内核文件,因此就产生了内核模块

    我们可以将一些不常用或者较新的硬件驱动编译成独立的模块,然后内核在正常运行过程中将需要的模块动态的加载到内核中以实现对其的支持

    核心模块存放路径:/lib/modules/$(uname -r)/kernel/

1.2、内核编译的目的

  • 新功能的需求
  • 原有内核过于臃肿
  • 与硬件搭配的稳定性问题
  • 其他需求

1.3、内核源码获取

  • 通过发行版获取

    如果只是想在当前的内核中添加某些功能,可以通过当前发行版来获取源码,其优点是:发行版中含有厂商设定好的预设值, 我们可以轻松的了解到与核心及模块有关的各项设定项目的参数值, 以便对我们的编译工作降低难度

  • 通过内核官网获取

    虽然通过发行版获取的内核文件能够降低我们编译的难度,但是无法对行硬件提供良好的支持,因此就需要从内核官网下载最新的内核源码进行编译,以获得最新的驱动支持

    kernel 官网:http://www.kernel.org/

    最新稳定版:https://cdn.kernel.org/pub/linux/kernel/v6.x/linux-6.2.13.tar.xz

  • 保留原有设置:利用patch升级核心源码

    patch 升级只提供对上一个版本的增量更新,因此只能对上一版本进行特定更新,而不能跨版本更新

1.4、内核源码目录简介

  • arch :与硬件平台有关的项目,大部分指的是 CPU 的类别,例如 x86、x86_64、Xen 虚拟支持等

  • block :与块设备相关的设置数据,块数据通常指的是大量储存媒介,还包括类似 ext4 等文件系统等

  • crypto :内核所支持的加密的技术,如 md5 或 des 等

  • Documentation :与内核有关的说明文件

  • drivers :一些硬件的驱动程序,如显示适配器、网卡、PCI 相关硬件等

  • firmware :一些旧硬件的固件

  • fs :内核所支持的 文件系统 ,如 vfat,、reiserfs、nfs 等

  • include :一些可以让其他程序调用的头文件

  • init :一些内核初始化的功能,包括挂载与 init 程序的调用等

  • ipc :定义 Linux 操作系统内各程序间的通信

  • kernel :定义内核的进程、内核状态、线程、进程的调度、进程的信号等

  • lib :一些函数库

  • mm :与内存单元有关的各项数据,包括 swap 与虚拟内存等

  • net :与网络有关的各项协议数据,还有防火墙模块 (net、ipv4、netfilter) 等

  • security :包括 selinux 等在内的安全性设置

  • sound :与音效有关的各项模块

  • virt :与虚拟化有关的信息,目前内核支持的是 KVM

2、内核功能选择

2.1、处理内核源码

我们不清楚下载的原码中有没有保留目标文件 (*.o) 以及相关的配置文件存在, 此时我们可以通过下面的方式来处理掉这些编译过程的目标文件以及配置文件

  • 将下载的源码文件解压到指定路径

    [root@vm-rocky9 ~]# tar -xvf linux-6.2.13.tar.xz -C /usr/src/kernels/
    
  • 处理编译过程的目标文件以及配置文件

    [root@vm-rocky9 ~]# cd /usr/src/kernels/linux-6.2.13/
    # 该命令会将之前进行过的内核功能选择文件同时删除掉
    # 因此只有第一次内核编译才需要操作
    [root@vm-rocky9 linux-6.2.13]# make mrproper
    # 删除前一次编译过程的残留数据
    [root@vm-rocky9 linux-6.2.13]# make clean
    

2.2、选择内核功能

/boot/ 目录下存在一个名为 config-xxx 的文件,该文件其实就是内核功能列表文件,接下来我们就需要创建这个文件,后续的编译就是通过这个文件来处理的。内核功能的选择,最后会在 /usr/src/kernels/linux-6.2.13/ 目录中生成一个隐藏的 .config 文件,这个文件就是 /boot/config-xxx 的文件

选择内核功能的方法很多,我们可以使用以下方式中的任何一种来选择内核的功能

  • make menuconfig

    最常使用的是命令行模式下面可以显示纯文本界面的方式,不需要启动 X Window 就能够选择核心功能选项

  • make oldconfig

    通过使用已存在的 .config 文件内容,使用该文件内的设定值为默认值,只将新版本内核中的新功能选项,列出让用户选择, 可以简化内核功能的选择过程,对于作为升级内核原码后的功能选择来说,是非常好用的一个选项

  • make xconfig

    通过以 Qt 为图形界面基础功能的图形化接口显示,需要具有 X window 的支持。KDE 就是通过 Qt 来设计的 X Window,因此如果使用 KDE,就可以使用此选项

  • make gconfig

    通过以 Gtk 为图形界面基础功能的图形化接口显示,需要具有 X window 的支持,GNOME 就是通过 Gtk 来设计的 X Window,因此如果使用 GNOME,可以使用选项

  • make config

    最原始的功能选择方法,每个选项都以列表方式一条一条的列出让你选择,如果设置错误只能够再次选择

2.2.1、全新配置选项

  • 执行功能选择

    [root@vm-rocky9 linux-6.2.13]# make menuconfig
    

    需要注意的是,在选择选项时,如果为 [*] 或者 <*> 则表示编译进内核;如果为 <M> 则表示编译成模块

  • 使用空格键选择或取消选项

  • 选择完毕后,选择【save】,即可生成 .config 文件

2.2.2、通过既有的设置来完成内核选项与功能的选择

如果我们只需要对内核做很小的修改,那么我们就可以使用现有的内核设置进行微调即可

  • 复制原来的配置文件

    [root@vm-rocky9 linux-6.2.13]# cp /boot/config-5.14.0-162.23.1.el9_1.x86_64 .config
    
  • 执行功能选择

    [root@vm-rocky9 linux-6.2.13]# make menuconfig
    

    在执行以上命令时,如果出现 scripts/kconfig/lxdialog/dialog.h:38:20: 致命错误:curses.h:没有那个文件或目录 的错误,需要安装 ncurses-devel 软件包

  • 使用左右键,选择【load】,导入配置文件,并做修改

  • 修改完毕后,选择【save】,即可生成新的 .config 文件,而原来的文件则自动重命名为 .config.old

  • 注意事项

    以 rocky Linux 为例,在导入原版本配置文件后,需要将以下参数关闭,否则会导致编译错误

    [root@vm-rocky9 linux-6.2.13]# vim .config
    CONFIG_DEBUG_INFO=y
    CONFIG_DEBUG_INFO_BTF=y
    CONFIG_SYSTEM_TRUSTED_KEYS="certs/rocky.pem"
    

3、内核的编译与安装

3.1、 编译内核与内核模块

在功能选择完毕后,接下来就是编译内核与核心,该工作非常简单,只需要三条命令即可(当然也可以合并为一条命令)

# 生成未经压缩的内核
[root@vm-rocky9 linux-6.2.13]# make vmlinux
# 仅生成核心模块
[root@vm-rocky9 linux-6.2.13]# make modules
# 生成经压缩过的核心(默认)
[root@vm-rocky9 linux-6.2.13]# make bzImage

# 以上三步合并执行
## 表示使用16线程同时编译
[root@vm-rocky9 linux-6.2.13]# make -j 16 all

/boot/ 目录下的内核文件都是经过压缩过的,因此,上述的操作中比较常用的是 modules 与 bzImage 这两个,bzImage 可以生成压缩过后的内核, 也就是我们用来做系统启动的信息,最后生成的文件默认会被存放在当前路径下

3.2、安装模块

模块的存放路径为: /lib/modules/$(uname -r) ,如果同一版本的模块被反复编译时,就会产生冲突,可以通过以下方法处理

  • 先将旧的模块目录重命名,然后才安装内核模块到目标路径中去

  • make menuconfig 时,在 【General setup】内的 ”Local version“ 修改成新的名称

安装模块只需要在当前路径执行 make modules_install 命令即可

[root@vm-rocky9 linux-6.2.13]# make modules_install
  ......
  INSTALL /lib/modules/6.2.13/kernel/net/qrtr/qrtr-mhi.ko
  SIGN    /lib/modules/6.2.13/kernel/net/qrtr/qrtr-mhi.ko
  INSTALL /lib/modules/6.2.13/kernel/virt/lib/irqbypass.ko
  SIGN    /lib/modules/6.2.13/kernel/virt/lib/irqbypass.ko
  DEPMOD  /lib/modules/6.2.13

3.3、安装新内核

grub2 不建议直接修改配置文件,而是通过让系统自动检测来处理 grub.cfg 这个配置文件的内容

  • 安装内核

    [root@vm-rocky9 linux-6.2.13]# make install
      INSTALL /boot
    
  • 编辑grub

    [root@vm-rocky9 linux-6.2.13]# grub2-mkconfig -o /boot/grub2/grub.cfg
    
  • 重新以新内核开机

  • 验证当前版本

    [root@vm-rocky9 ~]# uname -r
    6.2.13