实验一 Linux 内核编译

注意

  1. 使用 VMware 安装 Ubuntu,进行编译,系统映像下载地址【4.7G】(Ubuntu 官方

  2. 内核数和内存可以设置稍微大一些,这个会对后面编译时间造成影响,但不建议设置过大(不建议设置和实际机子相同),会导致外部系统非常卡顿

  3. 存储空间设置最好 70GB+,使用内核编译出来的文件可能会 20-30GB

  4. 存在大量的 sudo 操作,如果觉得麻烦可以切换到 root 账户

    • 如果是一台新的机器,可能会存在没设置 root 用户密码的情况,这个时候需要按照以下步骤进行设置;

      • 输入 sudo passwd root ,这时候会显示 New password:
      • 输入新密码(输入不会外显),然后显示 Retype new password:
      • 然后再次输入密码,如果显示 passwd: password unchanged 代表上述步骤有问题,可以重新执行;
    • 进入 root 用户;

      • 可以输入 sudo su ,然后输入 root 用户的密码,以 root 用户登录;
  5. 出现权限问题请前面加 sudo

前期准备

安装必要的依赖

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
sudo apt-get upgrade
sudo apt-get install libncurses5-dev
sudo apt-get install openssl
sudo apt-get install libssl-dev
sudo apt-get install build-essential
sudo apt-get install pkg-config
sudo apt-get install libc6-dev
sudo apt-get install bison
sudo apt-get install flex
sudo apt-get install libelf-dev
sudo apt install rpm rpm2cpio
sudo apt install rpmlint
sudo apt install libncurses5-dev gcc make rpm libssl-dev bison flex python3 coreutils diffutils patch
sudo apt upgrade
sudo apt install vim

可能会遇到网络问题,可以更换国内清华源(自行搜索),或者使用代理,可以查看 Linux 使用 V2ray 代理 ,可以对接 Azure 配置的 V2ray 服务器

下载并解压内核

1
2
3
4
5
6
7
8
# 切换目录到 /usr/src
cd /usr/src

# 下载源码包
sudo wget https://cdn.kernel.org/pub/linux/kernel/v6.x/linux-6.9.6.tar.xz

# 解压源码包到路径 /usr/src
sudo tar -xavf linux-6.9.6.tar.xz -C /usr/src

编译前处理

1
2
3
4
5
6
7
8
# 切换到预编译内核目录
cd /usr/src/linux-6.9.6

# 删除所有的编译生成文件、内核配置文件(.config文件)和各种备份文件,第一次编译使用
make mrproper

# 删除大多数的编译生成文件,但是会保留内核的配置文件.config,还有足够的编译支持来建立扩展模块
make clean

配置

配置文件

使用当前系统配置(建议使用),可以切换内核后保证驱动没有问题,但是编译出来的内容可能会很大

1
2
3
4
5
# 切换到预编译内核目录
cd /usr/src/linux-6.9.6

# 复制当前配置,当前配置在/boot/config-$(uname -r) .config
sudo cp -v /boot/config-$(uname -r) .config

使用默认配置(不推荐使用),会比较小,但可能会存在兼容性问题

1
2
3
4
5
# 切换到预编译内核目录
cd /usr/src/linux-6.9.6

# 使用默认配置
make defconfig

使用当前系统配置,修改部分内容

1
2
# 打开.config
vim .config

在 vim 中,使用 /debian 来搜索相关两行需要修改的内容

1
2
3
4
5
6
7
# CONFIG_SYSTEM_TRUSTED_KEYS="debian/canonical-certs.pem"
# 修改上面的行变为下面的样子,即删除debian/canonical-certs.pem
CONFIG_SYSTEM_TRUSTED_KEYS=""

# CONFIG_SYSTEM_REVOCATION_KEYS="debian/canonical-revoked-certs.pem"
# 修改上面的行变为下面的样子,即删除debian/canonical-revoked-certs.pem
CONFIG_SYSTEM_REVOCATION_KEYS=""

image-20240624195838657

启动编译配置界面(非必需)

1
2
3
4
5
# 启动配置界面
sudo make menuconfig

# 会打开一个新的界面
# 可以通过该图形界面对内核加载的模块编译选项进行调整,如修改编译后的内核名称、新添加之前系统缺少的模块等。
image-20240622095057617

进入 General setup -> ( ) Local version-append to kernel release ,输入新的版本号, 确认 .config 文件中 Local version 功能是否配置成功。

打开 .config 文件,搜索 CONFIG_LOCALVERSION ,发现已含有刚刚修改的版本附加信息。

image-20240622095548517

1
2
# 打开.config文件
vim .config

在 vim 中,使用 /CONFIG_LOCALVERSION 来搜索刚才的配置的定位,发现已含有刚刚修改的版本附加信息。

image-20240622100052084

编译安装内核(必须严格按照顺序)

1、编译内核

使用如下命令编译内核

1
2
3
4
5
6
7
8
9
10
11
12
# 查看cpu数量
nproc
# 显示所有CPU数量
nproc --all
# 编译内核
sudo make -j $(nproc --all) bzImage
# -j 代表多核同时处理,建议使用,可以加快速度

# 编译并且显示细节,可以排查错误用(无异常不需要使用)
# sudo make V=1 -j $(nproc --all) bzImage

# 报错请查看.config对应行的问题

如果显示错误,请确保所有依赖完成安装,这里时间会非常很久

最后显示 Kernel: arch/x86/boot/bzImage is ready (#1) 显示编译成功

2、编译并安装内核模块

1
2
3
4
5
6
7
8
#执行编译内核模块命令
sudo make modules -j $(nproc --all)

# 安装内核模块,默认安装的路径(/lib/modules/kernel-version/)
sudo make modules_install

# 指定安装路径,指定到开发板的文件系统中或者打包放到文件系统中
# sudo make modules_install INSTALL_MOD_PATH=~/rootfs

这里时间也会很久。

3、安装内核

1
2
# 将编译内核安装
make install

请确保输出的结果没有 Miss 或者 Error 等问题。

添加启动项

查看 boot 目录变化

1
2
# 命令执行后检索/boot目录是否包含最新内核
ls -l /boot | grep 6.9.6

image-20240623112142568

1
2
# 查看lib/modules下情况
ls /lib/modules/

image-20240623112526884

比如我的应该是 6.9.6.202406221707

添加启动项

1
2
3
4
5
# 进入/boot/grub/
cd /boot/grub

# 执行update-grub2 更新grub目录
update-grub2

出现这个代表添加启动项成功了。

image-20240623121150112

设置启动项加载时间(只需要配置一次)

1
2
3
4
5
# 备份配置文件
cp /etc/default/grub /etc/default/grub.bak

# 打开配置文件
vim /etc/default/grub

修改其中的几个参数为下面情况:

1
2
3
4
5
6
7
GRUB_DEFAULT=2

GRUB_TIMEOUT=10

# GRUB_TIMEOUT_STYLE=hidden

GRUB_CMDLINE_LINUX_DEFAULT="text"
1
2
# 更新grub
sudo update-grub

重启

1
2
# 重启
reboot

选择新内核

启动

10s 内,需要进行操作,不然会跳转到其他界面去,这个时候关机重启即可再次进入这个界面

选择 Advanced options for Ubuntu

image-20240623120334476

选择对应的内核即可,选择不带(recovery mode)

image-20240623120456245

查询内核版本号

1
2
# 查询内核版本号
uname -r

切换内核成功!

image-20240623120718887

附录

参考链接

如何编译 Linux Kernel

Linux–内核编译流程+系统调用(ubuntu)

虚拟机 Ubuntu20.04,在 linux-5.4.1 内核下添加一个简单的系统调用并编译该内核

常用编译命令

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
1.清理工作目标
make clean: 删除编译中间文件,但是保留配置
make mrproper:删除包括配置文件的所有构建文件
make distclean:执行mrproper所做的一切,并删除备份文件

2.配置内核
make menuconfig:文本图形方式配置内核
make oldconfig:基于当前的.config文件提示更新内核
make defconfig:生成默认的内核配置
make allmodconfig:所有的可选的选项构建成模块
make allyesconfig:生成全部选择是内核配置
make noconfig:生成全部选择否的内核配置

3.构建内核目标
make all:构建所有目标
make bzImage:构建内核映像
make modules:构建所有驱动
make dir/:构建指定目录
make dir/file.[s|o|i]:构建指定文件
make dir/file.ko:构建指定驱动

4.安装内核
make install:安装内核
make modules_install:安装驱动

5.打包工具
make rpm:生成内核的RMP包
make rpm-pkg:生成带源码的RPM包
make binrpm-pkg:生成包含内核和驱动的RMP包
make deb-pkg:生成包含内核和驱动的debian包

6.生成文档工具
make xmldocs:生成xml文档
make pdfdocs:生成pdf文档
make htmldocs:生成html文档

制作 generic 映像

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# 制作新的initrd,注意替换自己的版本号
mkinitramfs /lib/modules/6.9.6202406221707 -o /boot/initrd.img-6.9.6202406221707-generic
#这里很长时间不出现输出属于正常情况,结果不会输出任何东西

# 检查/boot下是否存在initrd.img-6.9.6202406221707-generic
ls /boot

# 复制bzImage
cp /usr/src/linux-6.9.6/arch/x86/boot/bzImage /boot/vmlinuz-6.9.6202406221707-generic

# 复制System.map
cp /usr/src/linux-6.9.6/System.map /boot/System.map-6.9.6202406221707-generic

# 复制config文件
cp /boot/config-6.9.6202406221707 /boot/config-6.9.6202406221707-generic

# 检查/boot下是否存在刚才复制的,分别为vmlinuz-6.9.6202406221707-generic、System.map-6.9.6202406221707-generic、config-6.9.6202406221707-generic
ls /boot