Ubuntu 编译 Linux 内核并从新内核启动
本文在一个 VirtualBox 的 Ubuntu VM 里编译新的Linux Kernel, 然后安装新kernel和模块, 然后更改系统从新内核启动.
下载 Linux 内核
可以选择从各种发布版本下载, 也可以选择从 github.com 下载. 下面选择从 Ubuntu 下载
$ git clone --depth 1 -b master git://git.launchpad.net/~ubuntu-kernel/ubuntu/+source/linux/+git/jammy
编译
要编译内核, 先安装必要的工具:
$ sudo apt update
$ sudo apt upgrade -y
$ sudo apt install git fakeroot build-essential ncurses-dev xz-utils libssl-dev bc flex bison libelf-dev -y
然后编译
$ cd jammy # 进入文件夹
$ make help # 查看 make 命令
$ make menuconfig # 更改配置, 并保存
$ ls -lah .config # 查看 .config 文件
$ make all -j 8
Kernel: arch/x86/boot/bzImage is ready (#1)
$ ls arch/x86/boot/bzImage # 查看 bzImage
-rw-rw-r-- 1 supra supra 11M Jul 1 11:40 arch/x86/boot/bzImage
$ find . -name *.ko # 查看新生成的模块
安装模块前 查看 /lib/modules/
文件夹
$ ls -lah /lib/modules/
drwxr-xr-x 3 root root 4.0K Jul 1 10:40 .
drwxr-xr-x 88 root root 4.0K Jul 1 11:07 ..
drwxr-xr-x 5 root root 4.0K Jul 1 10:40 5.15.0-76-generic
安装之前查看 /boot/
目录
$ uname -r # 查看当前运行的 kernel 版本
5.15.0-76-generic
$ ls -lah /boot/
drwxr-xr-x 4 root root 4.0K Jul 1 11:07 .
drwxr-xr-x 19 root root 4.0K Jul 1 10:45 ..
-rw------- 1 root root 6.0M Jun 15 17:47 System.map-5.15.0-76-generic
-rw-r--r-- 1 root root 256K Jun 15 17:47 config-5.15.0-76-generic
drwxr-xr-x 5 root root 4.0K Jul 1 10:40 grub
lrwxrwxrwx 1 root root 28 Jul 1 10:40 initrd.img -> initrd.img-5.15.0-76-generic
-rw-r--r-- 1 root root 106M Jul 1 11:07 initrd.img-5.15.0-76-generic
lrwxrwxrwx 1 root root 28 Jul 1 10:40 initrd.img.old -> initrd.img-5.15.0-76-generic
drwx------ 2 root root 16K Jul 1 10:37 lost+found
lrwxrwxrwx 1 root root 25 Jul 1 10:40 vmlinuz -> vmlinuz-5.15.0-76-generic
-rw------- 1 root root 12M Jun 15 18:21 vmlinuz-5.15.0-76-generic
lrwxrwxrwx 1 root root 25 Jul 1 10:40 vmlinuz.old -> vmlinuz-5.15.0-76-generic
安装 kernel 模块和 kernel image
安装 kernel
模块
$ sudo make INSTALL_MOD_STRIP=1 modules_install
$ ls -lah /lib/modules/ # 可以看到多了一个目录, 我们新编译安装的版本
drwxr-xr-x 4 root root 4.0K Jul 1 11:56 .
drwxr-xr-x 88 root root 4.0K Jul 1 11:07 ..
drwxr-xr-x 5 root root 4.0K Jul 1 10:40 5.15.0-76-generic
drwxr-xr-x 3 root root 4.0K Jul 1 11:58 5.15.92
安装新 kernel image
$ sudo make install
$ ls -lah /boot/ #查看 /boot/ 文件夹, 看到多了一个版本的一份: 5.15.92
drwxr-xr-x 4 root root 4.0K Jul 1 12:00 .
drwxr-xr-x 19 root root 4.0K Jul 1 10:45 ..
-rw------- 1 root root 6.0M Jun 15 17:47 System.map-5.15.0-76-generic
-rw-r--r-- 1 root root 5.6M Jul 1 11:59 System.map-5.15.92
-rw-r--r-- 1 root root 256K Jun 15 17:47 config-5.15.0-76-generic
-rw-r--r-- 1 root root 184K Jul 1 11:59 config-5.15.92
drwxr-xr-x 5 root root 4.0K Jul 1 12:00 grub
lrwxrwxrwx 1 root root 18 Jul 1 12:00 initrd.img -> initrd.img-5.15.92
-rw-r--r-- 1 root root 106M Jul 1 11:07 initrd.img-5.15.0-76-generic
-rw-r--r-- 1 root root 99M Jul 1 12:00 initrd.img-5.15.92
lrwxrwxrwx 1 root root 28 Jul 1 10:40 initrd.img.old -> initrd.img-5.15.0-76-generic
drwx------ 2 root root 16K Jul 1 10:37 lost+found
lrwxrwxrwx 1 root root 15 Jul 1 11:59 vmlinuz -> vmlinuz-5.15.92
-rw------- 1 root root 12M Jun 15 18:21 vmlinuz-5.15.0-76-generic
-rw-r--r-- 1 root root 11M Jul 1 11:59 vmlinuz-5.15.92
lrwxrwxrwx 1 root root 25 Jul 1 10:40 vmlinuz.old -> vmlinuz-5.15.0-76-generic
更新 grub
系统启动整体步骤如下:
BIOS -> GRUB -> vmlinuz -> initrd -> rootfs.
grub 核心部分
安装新 Kernel 之后, 要更新 GRUB 的配置. GRUB 的文件都在 /boot/grub/
目录, 配置文件: /boot/grub/grub.cfg
, kernel 模块和GRUB的 image 都在 /boot/grub/i386-pc
目录.
$ find /boot/grub/ -name *.img
/boot/grub/i386-pc/core.img
/boot/grub/i386-pc/boot.img
$ find /boot/grub/ -name *.mod
grub 配置
查看 /boot/grub/grub.cfg
我们可以看到我们新安装的 kernel 版本 5.15.92
已经在里面某个 menuentry 了, 这是在上面 make install
更新的.
$ cat /boot/grub/grub.cfg
menuentry 'Ubuntu, with Linux 5.15.92' --class ubuntu --class gnu-linux --class gnu --class os $menuentry_id_option 'gnulinux-5.15.92-advanced-84148117-53b4-4df1-bd78-8dd5d40c41da' {
recordfail
load_video
gfxmode $linux_gfx_mode
insmod gzio
if [ x$grub_platform = xxen ]; then insmod xzio; insmod lzopio; fi
insmod part_gpt
insmod ext2
set root='hd0,gpt2'
if [ x$feature_platform_search_hint = xy ]; then
search --no-floppy --fs-uuid --set=root --hint-bios=hd0,gpt2 --hint-efi=hd0,gpt2 --hint-baremetal=ahci0,gpt2 bea48426-830f-4bb9-9c08-f537663c02e6
else
search --no-floppy --fs-uuid --set=root bea48426-830f-4bb9-9c08-f537663c02e6
fi
echo 'Loading Linux 5.15.92 ...'
linux /vmlinuz-5.15.92 root=/dev/mapper/ubuntu--vg-ubuntu--lv ro
echo 'Loading initial ramdisk ...'
initrd /initrd.img-5.15.92
修改 grub 启动项
稍后如果我们重启, 就能在启动的时候选择我们新版本的kernel 了, 但是重启之前, 需要修改配置文件/etc/default/grub
. 把 GRUB_TIMEOUT_STYLE=hidden
注释掉, 把 GRUB_TIMEOUT
改成50秒.
GRUB_DEFAULT=0
# GRUB_TIMEOUT_STYLE=hidden
GRUB_TIMEOUT=50
更新上面的配置文件后, 需要运行下面的命令更新 GRUB:
$ sudo update-grub
Sourcing file `/etc/default/grub'
Sourcing file `/etc/default/grub.d/init-select.cfg'
Generating grub configuration file ...
Found linux image: /boot/vmlinuz-5.15.92
Found initrd image: /boot/initrd.img-5.15.92
Found linux image: /boot/vmlinuz-5.15.0-76-generic
Found initrd image: /boot/initrd.img-5.15.0-76-generic
Warning: os-prober will not be executed to detect other bootable partitions.
Systems on them will not be added to the GRUB boot configuration.
Check GRUB_DISABLE_OS_PROBER documentation entry.
done
最后重启:
$ sudo reboot
验证新kernel 版本
回到 VirtualBox 界面, 我们可以看到启动的界面, 可以选择 Advanced 菜单, 然后可以看到选择 kernel 界面:
其中每一项代表 /boot/grub/grub.cfg
的一个 menuentry. 选择我们的新kernel 然后启动.