⚙️ 以下是本篇文章所使用的环境:

  • 宿主机:MacOS Sonoma 14.4
  • 虚拟机:Ubuntu Server 20.04 LTS
  • VMware Fusion 13.5.1
  • Linux kernel 5.4.272

# 环境准备

# 下载项

# 下载 Linux 内核源码

官方网站下载 linux 内核源码

linux kernel

点击 [tarball],你会得到一个 linux-5.4.272.tar.xz 格式的打包文件,后续会用到。

# 下载 Ubuntu Server

  1. 选择 Ubuntu 的原因在于 Ubuntu 是目前市场占有率最高的 Linux 系统,这意味着他会有最好的支持和社区,便于查找 & 解决各种 bug。

  2. 选择 Server 版的原因在于 Server 版本舍弃了图形化界面,整体大小会小非常多,这意味着能给内核的编译 & 后续操作留更多的空间。

  3. 选择 20.04 版本的原因在于该版本默认使用 linux 5.4 的内核,减少我们后续自己编译的内核时可能出现的莫名 bug。

官方网站下载 Ubuntu Server 的镜像文件

ubuntu server

# 必要配置

# 虚拟机配置共享文件夹

⚠️ 本篇文章假定读者知道:如何使用虚拟机软件安装虚拟系统,如果不知道,请自行 Google~

在假定读者已经知道如何安装虚拟机的基础上,请注意

  1. 安装虚拟机时请给虚拟机最好分配 70G 以上的存储空间,因为编译内核所需空间非常大,使用默认配置的 20G 空间会导致没有足够空间编译内核。
  2. 最好分配 4 个以上 CPU 核心,核心数量直接影响内核的编译速度。
  3. 最好分配 4G 以上内存

由于采用的是没有图形化界面的 Server 版本,所以我们最好配置一下共享文件夹来方便在宿主机和虚拟机之间共享文件,配置过程如下:

  1. 找到「设置」=> 「共享」

    共享设置

  2. 创建一个文件夹用于共享,并将其权限改为「读与写」,点击「启用共享文件夹」(我这里共享文件夹命名为 share )。

    共享文件夹

  3. 将刚刚下载的内核文件放入文件夹中,并在虚拟机中执行如下指令:

    cd /mnt/hgfs/share
    ls

    如果一切顺利,你将会看到 linux-5.4.272.tar.xz 就在这里。「 所有共享文件夹会自动被挂载在 /mnt/hgfs 下,如果你的共享文件夹命名为其他的名字,请替换成自己的名字:) 」

    🙅 如果没有找到 share 文件夹,可以参考这篇博客

❗️linux虚拟机中无法写共享文件夹

笔者使用的是 MacOS,权限相对控制比较严格,共享文件夹的默认权限是只读,所以想让 linux 虚拟机可以向共享文件夹写入内容需要更改文件夹的权限,在 “share” 文件夹上点击「显示简介」,将本用户的权限改成「读与写」即可,如下图所示。

共享文件夹权限修改

# apt 换源

构建内核需要依赖大量工具,建议先更换一下 apt 源,方便下载。

# 备份之前的 sources.list
sudo cp /etc/apt/sources.list /etc/apt/sources.list.bak

然后替换 /etc/apt/sources.list 为以下内容并保存:

deb http://mirrors.aliyun.com/ubuntu/ focal main restricted universe multiverse
deb-src http://mirrors.aliyun.com/ubuntu/ focal main restricted universe multiverse
deb http://mirrors.aliyun.com/ubuntu/ focal-security main restricted universe multiverse
deb-src http://mirrors.aliyun.com/ubuntu/ focal-security main restricted universe multiverse
deb http://mirrors.aliyun.com/ubuntu/ focal-updates main restricted universe multiverse
deb-src http://mirrors.aliyun.com/ubuntu/ focal-updates main restricted universe multiverse
deb http://mirrors.aliyun.com/ubuntu/ focal-backports main restricted universe multiverse
deb-src http://mirrors.aliyun.com/ubuntu/ focal-backports main restricted universe multiverse
deb http://mirrors.aliyun.com/ubuntu/ focal-proposed main restricted universe multiverse
deb-src http://mirrors.aliyun.com/ubuntu/ focal-proposed main restricted universe multiverse

完成后使用 sudo apt update 来重新获取一下软件包缓存。

# 编译工具安装

安装编译内核时所需的工具,这里假设你使用的是一个纯净的 ubuntu 系统。

sudo apt install gcc g++ make git libncurses5-dev build-essential kernel-package libssl-dev libelf-dev dwarves flex bison

# 编译内核

# 解压 Linux 内核

# 将 Linux 内核从共享文件夹中复制到家目录下
sudo cp /mnt/hgfs/share/linux-5.4.272.tar.xz ~/ | cd ~ 
# 解压
xz -d linux-5.4.272.tar.xz
tar -xvf linux-5.4.272.tar
cd linux-5.4.272

# 配置 Linux 内核

Linux 内核的构建过程会查找 .config 文件,这是一个配置文件,用于指定 Linux 内核的所有可能的配置选项。这是必需的文件。

获取 Linux 内核的 .config 文件有两种方式:

  1. 使用你的 Linux 发行版的配置作为基础(推荐做法
  2. 使用默认的,通用的配置

💡 也有第三种方法,也就是从零开始,手动配置每一个选项,但注意,这需要配置超过 12,000 个选项。并不推荐这种方式,因为手动配置所有选项将花费大量的时间,并且你还需要理解每个启用和禁用选项的含义。

以下是第一种方式:

cd linux-*/
# 复制你的 Ubuntu 的配置文件
sudo cp /boot/config-"$(uname -r)" .config

# 更新 config 配置

由于我们使用的是 “旧的配置文件”(当前保存为 .config ,这是发行版配置的一个副本),所以需要检查从上一版本以来 Linux 代码库中新加的任何配置选项。如果找到任何「新的、未配置」 的选项,该选项的默认配置值会被使用,并会对 .config 文件进行更新。

原来的 .config 文件将被重命名为 .config.old 进行备份,并将新的更改写入至 .config 文件。

make olddefconfig

# 添加必要配置

构建内核时内核模块会使用一个签名证书,默认情况下,你的计算机并不包含这个证书。我们可以用以下命令告诉编译器,自行生成一个签名证书并在编译时使用。

./scripts/config --file .config --set-str SYSTEM_TRUSTED_KEYS ''
./scripts/config --file .config --set-str SYSTEM_REVOCATION_KEYS ''

我们还可以为自定义内核构建添加一个标签。我使用字符串 -gality 作为标签。这样当运行 uname -r 命令时,就会显示 5.4.272-gality 了:)

./scripts/config --file .config --set-str LOCALVERSION "-gality"

# 编译

实际的编译很简单,也很漫长(可能 1~3 小时,如果顺利的话~

# -j 参数指定使用多个核心来加速编译过程
make -j$(nproc)

如果很不幸,你出现了 No space left on device 的错误,那么意味着你并没有好好阅读之前的内容,不过,你可以参考这篇文章来让解决问题。

# 安装内核

# 安装模块

将已经编译好的模块安装到内核中

sudo make modules_install

# 安装 Linux 内核头文件 (可选)

如果打算尝试自行编写模块,可能会需要 Linux 内核提供的头文件。可使用如下命令来安装头文件:

sudo make headers_install

这些头文件会被安装到 /usr 目录。同时还会在 /usr 目录内创建子目录 include/linux ,然后将头文件安装到 /usr/include/linux

# 安装内核

安装内核,这个过程会更新 boot 和 grub

sudo make install

此时,可以重启 reboot 来测试新内核是否成功安装:

$ uname -r
5.4.272-gality # Yeah~

# 安装失败报错

如果在安装内核时出现类似如下报错:

...
update-initramfs: Generating /boot/initrd.img-5.4.0.52-generic
Error 24 : Write error : cannot write compressed block
E: mkinitramfs failure cpio 141 lz4 -9 -I 24
update-initramfs: failed for /boot/initrd.img-5.4.0-52-generic with 1.
...

代表写入 /boot 失败,可以按如下步骤确定原因:

  1. 判断是否有 /boot 目录的权限(是否用 sudo 了? /boot 和所有文件是否属于 root ?)
  2. /boot 目录是否有足够剩余空间( /boot 可能被过时的内核填满了)?
  3. 是否是驱动的问题(能否在别的位置写入文件)?

如果是全新的 ubuntu 系统用于安装内核,大概率不会出现问题,笔者本身遇到这个问题是因为之前手动编译安装过一次内核,第二次安装时出现这个问题,解决方法如下:

sudo apt list --installed | grep linux-image # 列出所有安装过的内核
sudo apt remove linux-image-5.4.0-54-generic # 删除过时的内核
sudo apt autoremove # 自动删除过时内核的依赖

重复上述操作,直到 sudo apt list --installed | grep linux-image 后没有出现任何版本内核。然后重新 sudo make install 即可成功安装内核。


更新于 阅读次数

请我喝[茶]~( ̄▽ ̄)~*

Gality 微信支付

微信支付

Gality 支付宝

支付宝