系统启动后如何确定内核镜像的完整路径及所在分区?
如何确切定位内核镜像的分区与路径,以及initramfs的访问问题
好问题!依赖/proc/cmdline或者默认/boot挂载点确实不太可靠——毕竟有些系统会把/boot放在单独分区,甚至有嵌入式系统会把内核镜像放在非标准路径,或者后期移动过镜像文件。下面给你几个靠谱的方法:
一、确切定位内核镜像的分区与路径
1. 结合内核版本查找+挂载信息验证
首先获取当前运行的内核版本,再定位对应的镜像文件,最后查它的挂载分区:
# 获取当前内核版本 KERNEL_VER=$(uname -r) # 查找常见命名的内核镜像(vmlinuz/bzImage) KERNEL_PATH=$(find /boot -name "vmlinuz-$KERNEL_VER" -o -name "bzImage-$KERNEL_VER" 2>/dev/null) # 如果没找到,扩大到根目录搜索(适合非标准路径的系统) if [ -z "$KERNEL_PATH" ]; then KERNEL_PATH=$(find / -name "vmlinuz-$KERNEL_VER" -o -name "bzImage-$KERNEL_VER" 2>/dev/null | grep -v "/proc" | grep -v "/sys") fi # 查看镜像所在的分区和挂载点 if [ -n "$KERNEL_PATH" ]; then findmnt -n -o SOURCE,TARGET "$KERNEL_PATH" fi
这个方法会直接输出类似/dev/sda1 /boot的结果,明确告诉你分区和挂载点。
2. 从启动加载器配置文件读取
绝大多数系统的启动加载器会记录内核镜像的准确路径:
- GRUB2系统:查看GRUB配置里对应当前内核的条目:
输出里的cat /boot/grub/grub.cfg | grep -A5 -B5 "$(uname -r)"linux行就是内核的完整路径,set root=行则标注了启动分区(比如hd0,msdos1),可以用grub-probe --target=device /boot把这个GRUB格式的分区转换成系统识别的设备名(比如/dev/sda1)。 - LILO/SysVinit系统:查看
/etc/lilo.conf,里面的image字段就是内核路径,root字段对应分区。
3. 从内核启动日志获取最原始的加载信息
内核启动时会记录自己是从哪个设备加载的,这是最准确的来源:
# 用dmesg查看(通用) dmesg | grep -i "loaded kernel\|kernel image" # 或者用journalctl(systemd系统) journalctl -k | grep -i "loaded kernel\|kernel image"
比如输出可能是:Loaded kernel from /dev/sda1:/boot/vmlinuz-5.15.0-78-generic,直接给出了分区和完整路径。
二、initramfs能否通过知名路径访问内核镜像?
答案是通常不行,原因有两个:
- initramfs是一个临时的内存根文件系统,在实际根分区(包括
/boot)挂载之前运行,默认情况下/boot并没有被挂载到initramfs的文件系统里,自然无法访问磁盘上的内核镜像。 - 退一步说,initramfs根本不需要访问内核镜像——内核已经加载到内存中运行了,initramfs的核心作用是挂载真实根文件系统,然后完成系统切换,内核本身已经在内存里,不需要再读取磁盘上的镜像文件。
唯一的例外是:如果你的系统采用EFI启动,且EFI系统分区(ESP)在initramfs阶段被显式挂载到某个路径(比如/efi),而内核镜像恰好放在ESP里,这时候可以通过该挂载路径访问,但这不属于“知名路径”,完全取决于你的启动配置。
内容的提问来源于stack exchange,提问作者patrick h




