Red Hat Enterprise Linux 8 的新玩意 第4篇 通过`grub`配置Kernel启动参数

Red Hat Enterprise Linux 8 (RHEL8) 的新玩意 第4篇 通过grub配置Kernel启动参数

内核启动参数, 简单的说就是可以给内核传递参数,并且用于控制内核行为方式.

1 通常来说我们有3种方式可以给内核传递参数

1.1 在编译内核时侯,添加我们要的参数

1.2 内核启动时通过boootloader添加,比如通过gurb或者uboot (arm或者ppc平台)

1.3 在系统运行的时候,通过修改/proc/sys里面对应的文件.

2 这里, 我们讲第二项(内核启动时通过boootloader添加,比如通过gurb或者uboot); 通常来说我们可以通过直接修改/boot/grub2/grub.cfg文件来现实.但是我们看到,在RHEL8上面,/boot/grub2/grub.cfg居然没有我们熟悉linux /boot/vmlinuz-xxx.x86_64 root=UUID=xxx的条目. 这是什么回事,比如我们要重定向串口输出,添加console=ttyS0,115200n8这个参数要加到什么地方?不要紧,让我们先来看看\boot下面都有些什么文件.

3 查看启动目录/boot/的内容, 我们知道系统是启动这个内核vmlinuz-4.18.0-80.el8.x86_64

1
2
3
4
5
6
[root@vm3_rhel8 ~]# cd /boot/ && ls
config-4.18.0-80.el8.x86_64 initramfs-4.18.0-80.el8.x86_64kdump.img
efi loader
grub2 System.map-4.18.0-80.el8.x86_64
initramfs-0-rescue-54d1217dfdda4592a9e30059e470cf24.img vmlinuz-0-rescue-54d1217dfdda4592a9e30059e470cf24
initramfs-4.18.0-80.el8.x86_64.img vmlinuz-4.18.0-80.el8.x86_64

4 知道了系统内核vmlinuz-4.18.0-80.el8.x86_64的名字,我们来找找有配置它的地方,来grub一下

1
2
3
[root@vm3_rhel8 boot]# grep -n "vmlinuz-4.18.0-80.el8.x86_64" -r ./
./loader/entries/54d1217dfdda4592a9e30059e470cf24-4.18.0-80.el8.x86_64.conf:3:linux /boot/vmlinuz-4.18.0-80.el8.x86_64
./.vmlinuz-4.18.0-80.el8.x86_64.hmac:1:54d1217dfdda4592a9e30059e470cf24 /boot/vmlinuz-4.18.0-80.el8.x86_64

5 好了, 我们找到了相关的文件./loader/entries/54d1217dfdda4592a9e30059e470cf24-4.18.0-80.el8.x86_64.conf, 那就来看看里面都有些什么cat一下.

1
2
3
4
5
6
7
8
9
title Red Hat Enterprise Linux (4.18.0-80.el8.x86_64) 8.0 (Ootpa)
version 4.18.0-80.el8.x86_64
linux /boot/vmlinuz-4.18.0-80.el8.x86_64
initrd /boot/initramfs-4.18.0-80.el8.x86_64.img $tuned_initrd
options $kernelopts $tuned_params
id rhel-20190313123447-4.18.0-80.el8.x86_64
grub_users $grub_users
grub_arg --unrestricted
grub_class kernel./loader/entries/54d1217dfdda4592a9e30059e470cf24-4.18.0-80.el8.x86_64.conf

6 有熟悉的面孔吧,看起来我们可以在这配置内核的参数,而且变量kernelopts似乎是对应的启动参数.

1
2
3
[root@vm3_rhel8 boot]# grep -n "kernelopts" -r ./
./grub2/grubenv:3:kernelopts=root=UUID=06246343-6949-4824-a96f-6ce27ff92cd5 ro crashkernel=auto
./loader/entries/54d1217dfdda4592a9e30059e470cf24-0-rescue.conf:5:options $kernelopts

7 它在这里定义,那我们就直接编辑添加我们需要的内核参数就好了.改一下,变成这样.

1
./grub2/grubenv:3:kernelopts=root=UUID=06246343-6949-4824-a96f-6ce27ff92cd5 ro crashkernel=auto console=ttyS0,115200n8 console=tty0

8 深入一些,那这个options $kernelopts 又是怎么就能传递到内核去的呢?

8.1 小Tips,先来打开个debug开关. 我们可以添加set debug=blscfg(grub会通过函数grub_dprintf输出对应的debug消息)到文件/boot/grub2/grub.cfg; 然后注意把启动设置到一个不存在menu(比如set pager=1). 这样的话,gurb就会因为找不到启动项而停住,那我们就可以看到输出呢. 另外多说一句,还有这些模块可以用来调试(有兴趣可以试试看).

1
2
"acpi","ahci","arcdisk","archelp","ata","atkeyb","badram","blscfg","bootp","bsd","btrfs","chain","cros","crypt","cryptodisk","devalias","disk",
"diskfilter","dl","dns","drivemap","efi","efidisk","efiemu","efiemu","system_table,"efinet","efinetfs","ehci","elf","exfat","expand","fb","fdtbus","fixvideo","font","fs","fw_path","geli","gpt","hostdisk","init","keystatus","linux","loader","luks","memdisk","menu","mmap","modules","multiboot_loader","nativedisk","net","ohci","partition","pata","play","tempo"pmtimer","reiserfs","reiserfs_blocktype","reiserfs_tree","relocator","scripting","scsi","secureboot","serial","syslinux","tftp","ubootdisk","uhci","usb","usb_keyboard","usbms","video","xen","xen_loader","xnu","zfs",

8.2 通过查看grub的debug输出. 看到了options $kerneloptsgrub启动时被调用了,所以对应的内核参数也被导入了.

1
commands/blscfg.c:135: new keyval at 0xbfe42aa0:options:$kernelopts $tuned_params

8.3 再深入一些,那options $kernelopts具体又是怎么调进去的呢?好办,快速瞄个代码(呵呵,这就是开源的优势之一; 想知道内幕,下个代码瞄瞄). 通过查阅代码,grub里面的与之对应的函数大概流程如下,都简明易懂,就不多解析咯.

1
2
3
4
5
1. GRUB_MOD_INIT(blscfg) // gurb在启动时,初始化'blscfg'
2. grub_cmd_blscfg (grub_extcmd_context_t ctxt UNUSED,int argc UNUSED,char **args UNUSED) // 命令的实现
3. find_entry (struct find_entry_info *info) // 查找启动列表
4. read_entry (const char *filename,const struct grub_dirhook_info *dirhook_info UNUSED,void *data) // 找到就将列表读出来
5. bls_add_keyval(struct bls_entry *entry, char *key, char *val) // 把列表里面参数解析并添加

9 到此,内核启动时通过boootloader添加启动参数就结束了. 多说一句,grub2-mkconfig命令也可以有类似功能.

好, Red Hat Enterprise Linux 8 (RHEL8) 的新玩意 第4篇 通过grub配置Kernel启动参数就介绍完了. 想要了解更多? 可以参考 GRUB Manual 或者源代码.
想要亲手玩一下新玩具? 请随时去 https://www.redhat.com 下载最新的 REHL 8

也欢迎关注 addos 微信公众号获取更多的,有意思的新玩具 :-)