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 界面:
grub.png

其中每一项代表 /boot/grub/grub.cfg的一个 menuentry. 选择我们的新kernel 然后启动.

标签: none

添加新评论