浅析 GRUB 如何加载 Linux kernel
浅析 GRUB 如何加载 Linux kernel
前言
对于 GRUB 的加载流程,网上绝大部分都是写对 menu.lst, grub.cfg 这些 GRUB 配置文件的编写流程,就像是写脚本语言一样,用些关键字就能让 PC机能正确启动桌面 Linux 了。但这只是 GRUB 的使用,而不是GRUB的分析。
本来是没有想要探究 GRUB 的想法,直到我在自制toy kernel 的学习中进入了 “虚拟内存管理”这一章节。很多介绍虚拟内存管理的时候都会说到 Linux 的内存管理,Linux 内核会加载到系统 3G~4G 的虚拟内存中, 但 GRUB 是没有开启虚拟内存的,Linux 内核的加载是被谁,又是如何加载相应段到 3G~4G 区的呢。
分析 kernel
vmLinux
我们看下内核源码编译后的最原始文件 vmLinux。该文件是 ELF 文件,使用 readelf 读下该文件的 Section header.
这里只截了几个段显示,后面的段都类似. 可以看到这些需要加载的段的地址的确是在 0xC0000000 之后。但 vmLinux 并不是可引导的Linux 内核文件。
Linux启动的相关信息一般都在 `/boot` 下,我们看下里面的内容.
可以看到 grub 文件夹,grub 就是引导 Linux 进行启动的 bootloader,我们看下 `/boot/grub/grub.cfg` 文件的内容。
menuentry 'Linux Mint 17 {
recordfail
gfxmode $linux_gfx_mode
insmod gzio
insmod part_msdos
insmod ext2
set root='hd0,msdos1'
linux /boot/vmlinuz-3.13.0-24-generic
initrd /boot/initrd.img-3.13.0-24-generic
}
带有 linux 的一行就指定了启动的内核,可以看到不是 vmlinux 文件,而是 vmlinuz 文件。
vmlinuz
搜索后可以看到 vmlinuz 是**可引导的,压缩**的内核。 initrd 是"initial ramdisk" 的简写,是临时的虚拟磁盘,暂时不讨论。 因为我电脑上 vmlinuz 是64 bit的,对 64bit不太了解,所以找了个 32bit 的vmlinuz 文件来作解析。先试试`readelf`命令。
# readelf -S vmlinuz
readelf:错误: Unable to read in 0x7269 bytes of 节头
readelf:错误: 不是 ELF 文件 - 它开头的 magic 字节错误
不是 ELF 文件, 那试试 `objdump` 吧。
# objdump -afh vmlinuz
objdump: vmlinuz: 不可识别的文件格式
还是不行。
这个时候之所以会相当用这些命令看 vmlinuz 文件的段信息,因为在我的 toy kernel 中使用的是 ELF 文件,而且是使用 grub 加载的,对于 ELF 文件来说内部保护若干 section, 执行时这些 section 必须要在特地的内存地址上. 使用 `readelf` 查看toy kernel 的 section header 信息如下.
可以看到 Addr 段就是内核运行时这些段在内存中的地址。而加载我的内核的 grub 的配置如下
title toy kernel
root (fd0)
kernel /zkernel
module /initrd
vmlinuz 之所以叫做压缩的内核,是因为它是使用 gzip 压缩后得来,而且不单单是个纯数据包,在文件开头部分内嵌有 gzip 解压缩代码,相当于"自解压"。我的内核需要由grub加载好相应的 section, 但 vmlinuz 都读不出来段如何让 grub 加载?
其实答案就在上面的 grub 配置文件里,在 linux 中声明内核使用的是 *linux* 关键字,在我的配置中声明内核使用的却是 *kernel*. 可以明确看出,grub对 linux 的加载是特殊对待的, 但具体怎么特使对待,只能从源代码里看了。
如何在Ubuntu12.04/12.10中重装或修复Grub2引导
Linux启动引导过程 grub和mbr
grub 的安装与使用
grub引导程序配置文件分析
CentOS 6.4 grub加密码
CentOS GRUB引导错误无法进入系统解决办法
更多详情见请继续阅读下一页的精彩内容:
|
评论暂时关闭