操作系统实战 45 讲
彭东
网名 LMOS,Intel 傲腾项目关键开发者
65203 人已学习
新⼈⾸单¥68
登录后,你可以任选4讲全文学习
课程目录
已完结/共 60 讲
尝尝鲜:从一个Hello到另一个Hello (2讲)
特别放送 (1讲)
操作系统实战 45 讲
15
15
1.0x
00:00/00:00
登录|注册

14 | Linux初始化(上):GRUB与vmlinuz的结构

定义解压信息
包含vmlinux.bin.gz文件
piggy.S文件生成
vmlinux文件生成
vmlinux.bin文件生成
setup.bin文件生成
bzImage文件生成规则
控制权转交给GRUB
硬盘上的MBR
搜索可引导的设备
加载中断服务程序
构建BIOS数据区
构建中断表
建立中断表和中断服务程序
枚举本地设备进行初始化
复制自身到内存
检查并初始化内存
初始化CPU
GRUB加载Linux的内核映像vmlinuz
BIOS加载引导设备中引导扇区
BIOS自检
为什么要用C代码mkpiggy程序生成piggy.S文件,并包含vmlinux.bin.gz文件呢?
piggy.S文件结构
vmlinuz文件的生成过程
core.img加载Linux系统的vmlinuz内核文件
重要文件boot.img和core.img
GRUB加载分成多个步骤
启动设备初始化
BIOS建立中断表和中断服务程序
BIOS启动流程
x86平台的启动流程
思考题
详解vmlinuz文件结构
GRUB是如何启动的
从BIOS到GRUB
全局流程
Linux初始化(上):GRUB与vmlinuz的结构

该思维导图由 AI 生成,仅供参考

你好,我是 LMOS。
在前面的课程中,我们建好了二级引导器,启动了我们的 Cosmos,并进行了我们 Cosmos 的 Hal 层初始化。
我会用两节课带你领会 Linux 怎样做初始化。虽然我们自己具体实现过了初始化,不过我们也不妨看看 Linux 的初始化流程,借鉴一下 Linux 开发者的玩法。
这节课,我会先为你梳理启动的整体流程,重点为你解读 Linux 上 GRUB 是怎样启动,以及内核里的“实权人物”——vmlinuz 内核文件是如何产生和运转的。下节课,我们从 setup.bin 文件的 _start 函数入手,研究 Linux 初始化流程。
好,接下来我们从全局流程讲起,正式进入今天的学习。

全局流程

x86 平台的启动流程,是非常复杂的。为了帮助你理解,我们先从全局粗略地看一看整体流程,然后一步步细化。
在机器加电后,BIOS 会进行自检,然后由 BIOS 加载引导设备中引导扇区。在安装有 Linux 操作系统的情况下,在引导扇区里,通常是安装的 GRUB 的一小段程序(安装 windows 的情况则不同)。最后,GRUB 会加载 Linux 的内核映像 vmlinuz,如下图所示。
x86的全局启动流程示意图
上图中的引导设备通常是机器中的硬盘,但也可以是 U 盘或者光盘甚至是软盘。BIOS 会自动读取保存在 CMOS 中的引导设备信息。
确认放弃笔记?
放弃后所记笔记将不保留。
新功能上线,你的历史笔记已初始化为私密笔记,是否一键批量公开?
批量公开的笔记不会为你同步至部落
公开
同步至部落
取消
完成
0/2000
荧光笔
直线
曲线
笔记
复制
AI
  • 深入了解
  • 翻译
    • 英语
    • 中文简体
    • 中文繁体
    • 法语
    • 德语
    • 日语
    • 韩语
    • 俄语
    • 西班牙语
    • 阿拉伯语
  • 解释
  • 总结

本文深入解读了Linux初始化的流程和关键文件,重点介绍了vmlinuz文件的结构和生成过程。文章详细分析了bzImage文件的生成过程,包括setup.bin、vmlinux.bin和tools/build等文件的作用和生成规则。通过对setup.bin和vmlinux.bin的结构分析,读者可以深入了解这两个关键文件的生成过程和内部构成。此外,文章还介绍了vmlinux文件的生成过程,从Linux源代码编译到链接生成vmlinux文件的整个过程。通过对vmlinux文件的生成过程的解析,读者可以全面了解Linux内核的编译和链接过程。整体来看,本文通过详细解读Linux初始化的流程和关键文件,帮助读者深入了解了Linux系统启动的技术特点和关键步骤。

仅可试看部分内容,如需阅读全部内容,请付费购买文章所属专栏
《操作系统实战 45 讲》
新⼈⾸单¥68
立即购买
登录 后留言

全部留言(14)

  • 最新
  • 精选
  • neohope
    大体上整理了一下,有问题欢迎帮忙指出【上】: 操作系统的启动分为两个阶段:引导boot和启动startup,本节主要还是boot过程: BIOS->GRUG1->GRUB1.5->GRUB2->Linux内核【环境硬盘引导、MBR分区】 1、按电源键,系统加电 2、主板通电 CPU加电时,会默认设置[CS:IP]为[0XF000:0XFFF0],根据实模式下寻址规则,CPU指向0XFFFF0 这个地址正是BIOS启动程序位置,而BIOS访问方式与内存一致,所以CPU可以直接读取命令并执行 3、BIOS执行 3.1、BIOS首先执行POST自检,包括主板、内存、外设等,遇到问题则报警并停止引导 3.2、BIOS对设备执行简单的初始化工作 3.3、BIOS 会在内存中: 建立中断表(0x00000~0x003FF) 构建 BIOS 数据区(0x00400~0x004FF) 加载了中断服务程序(0x0e05b~0x1005A) 3.4、BIOS根据设备启动顺序,依次判断是否可以启动 比如先检查光驱能否启动 然后依次检查硬盘是否可以启动【硬盘分区的时候,设置为活动分区】 4、硬盘引导 4.1、先说下寻址方式,与扇区编号的事情 最传统的磁盘寻址方式为CHS,由三个参数决定读取哪个扇区:磁头(Heads)、柱面(Cylinder)、扇区(Sector) 磁头数【8位】,从0开始,最大255【微软DOS系统,只能用255个】,决定了读取哪个盘片的哪个面【一盘两面】 柱面数【10位】,从0开始,最大1023【决定了读取哪个磁道,磁道无论长短都会划分为相同扇区数】 扇区数【6位】,从1开始,最大数 63【CHS中扇区从1开始,而逻辑划分中扇区从0开始,经常会造成很多误解】 每个扇区为512字节 4.2、然后说下引导方式 BIOS在发现硬盘启动标志后,BIOS会引发INT 19H中断 这个操作,会将MBR【逻辑0扇区】,也就是磁盘CHS【磁头0,柱面0,扇区1】,读取到内存[0:7C00h],然后执行其代码【GRUB1阶段】,至此BIOS把主动权交给了GRUB1阶段代码 MBR扇区为512字节,扇区最后分区表至少需要66字节【64字节DPT+2字节引导标志】,所以这段代码最多只能有446字节,grub中对应的就是引导镜像boot.img boot.img的任务就是,定位,并通过BIOS INT13中断读取1.5阶段代码,并运行 5、Grub1.5阶段 5.1、先说一下MBR GAP 据说微软DOS系统原因,第一个分区的起始逻辑扇区是63扇区,在MBR【0扇区】和分布表之间【63扇区】,存在62个空白扇区,共 31KB。 Grub1.5阶段代码就安装在这里。 5.2、上面提到,boot.img主要功能就是找到并加载Grub1.5阶段代码,并切换执行。 Grub1.5阶段代码是core.img,其主要功能就是加载文件系统驱动,挂载文件系统, 位加载并运行GRUB2阶段代码。 core.img包括多个映像和模块: diskboot.img【1.5阶段引导程序】,存在于MBR GAP第一个扇区;【这里是硬盘启动的情况,如果是cd启动就会是cdboot.img】 lzma_decompress.img【解压程序】 kernel.img【grub核心代码】,会【压缩存放】 biosdisk.mod【磁盘驱动】、Part_msdos.mod【MBR分区支持】、Ext2.mod【EXT文件系统】等,会【压缩存放】 其实boot.img只加载了core.img的第一个扇区【存放diskboot.img】,然后控制权就交出去了,grub阶段1代码使命结束。 diskboot.img知道后续每个文件的位置,会继续通过BIOS中断读取扇区,加载余下的部分并转交控制权,包括: 加载lzma_decompress.img,从而可以解压被压缩的模块 加载kernel.img,并转交控制权给kernel.img kernel.img的grub_main函数会调用grub_load_modules函数加载各个mod模块 加载各个mod后,grub就支持文件系统了,访问磁盘不需要再依靠BIOS的中断以扇区为单位读取了,终于可以使用文件系统了

    作者回复: 6666

    2021-06-10
    7
    55
  • neohope
    大体上整理了一下,有问题欢迎帮忙指出【下】: 6、GRUB2阶段 现在grub就能访问boot/grub及其子目录了 kernel.img接着调用grub_load_normal_mode加载normal模块 normal模块读取解析文件grub.cfg,查看有哪些命令,比如发现了linux、initrd这几个命令,需要linux模块 normal模块会根据command.lst,定位并加载用到的linux模块【一般在/boot/grub2/i386-pc目录】 当然,同时需要完成初始化显示、载入字体等工作 接下来Grub就会给咱们展示启动菜单了 7、选择启动菜单 7.1、引导协议 引导程序加载内核,前提是确定好数据交换方式,叫做引导协议,内核中引导协议相关部分的代码在arch/x86/boot/header.S中,内核会在这个文件中标明自己的对齐要求、是否可以重定位以及希望的加载地址等信息。同时也会预留空位,由引导加载程序在加载内核时填充,比如initramfs的加载位置和大小等信息。 引导加载程序和内核均为此定义了一个结构体linux_kernel_params,称为引导参数,用于参数设定。Grub会在把控制权移交给内核之前,填充好linux_kernel_params结构体。如果用户要通过grub向内核传递启动参数,即grub.cfg中linux后面的命令行参数。Grub也会把这部分信息关联到引导参数结构体中。 7.2、开始引导 Linux内核的相关文件位于/boot 目录下,文件名均带有前缀 vmlinuz。 咱们选择对应的菜单后,Grub会开始执行对应命令,定位、加载、初始化内核,并移交到内核继续执行。 调用linux模块中的linux命令,加载linux内核 调用linux模块中的initrd命令,填充initramfs信息,然后Grub会把控制权移交给内核。 内核此时开始执行,同时也就可以读取linux_kernel_params结构体的数据了 boot阶段结束,开始进入startup阶段。

    作者回复: 大佬 很强

    2021-06-10
    32
  • 178
    vmlinuz是可引导的、压缩的内核。“vm”代表 “Virtual Memory”,linu代表“Linux”,z代表压缩。是个有故事的缩写

    作者回复: 对的

    2021-11-10
    6
  • Fan
    请问,为什么要用 C 代码 mkpiggy 程序生成 piggy.S 文件,并包含 vmlinux.bin.gz 文件呢? 看了这下生成的这个piggy.S 文件 主要的就是这行代码 .incbin "arch/x86/boot/compressed/vmlinux.bin.gz" 通过C 代码的形式,可以传入不同的参数来设置不同的压缩包vmlinux.bin.xx 来生成piggy.S 。

    作者回复: 这就是开源作者的喜好了

    2021-06-09
    6
  • 孤星可
    尝试实现了 lmoskrlimg 的逻辑(即 Cosmos.eki 的生成),有兴趣可以看看。 https://github.com/guxingke/demo/blob/master/bytes-demo/src/main/java/com/gxk/demo/Main.java

    作者回复: 6666

    2021-06-10
    5
  • Qfeng
    一、简单总结: 1. CPU上电启动BIOS(ROM) CPU硬件被设计成在加电的瞬间,强制将 CS 寄存器的值设置为 0XF000,IP 寄存器的值设置为 0XFFF0。 CS:IP 为 0XFFFF0 的这个物理地址上连接了主板上的一块小的 ROM 芯片,BIOS 程序就被固化在该 ROM 芯片里。 总结:CPU上电后硬件自动将 CS:IP 指向地址 0XFFFF0,这里存放了BIOS程序的入口地址,达到启动 BIOS 的目的。 (注:这个ROM芯片的访问机制和寻址方式和内存一样,只是它在断电时不会丢失数据,在常规下也不能往这里写入数据,它是一种只读内存。) 2. ROM BIOS 初始化CPU和内存,将自己拷贝到内存,执行环境跳转到内存(DDR) 3. DDR BIOS 1)设备初始化 2)在内存中建立中断服务程序表(0x00000~0x003FF,1KB,256个条目), BIOS 数据区(0x00400~0x004FF)和中断服务程序(0x0E05B~1005B,8KB) 3)搜索可引导的外部存储器,并启动其中的程序。(包括:硬盘,U盘,软驱,光驱和网络设备等) 4)Linux从硬盘启动时,硬盘中名为MRB的第一个扇区包含的GRUB 启动程序(安装GRUB时自动写入)和分区表被 BIOS 装载到 0x7c00 地址开始的内存空间, 至此BIOS使命结束,控制权交给GRUB。 4. GRUB 启动 1)GRUB包含 boot.img和core.img两部分,硬盘MRB空间有限只包含boot.img,boot.img中包含core.img存放的硬盘扇区号 2)core.img 文件是由 GRUB 安装程序根据安装时环境信息,用其它 GRUB 的模块文件动态生成,主要包含diskboot.img,kernel.img和其他功能模块。 GRUB 的 core.img 文件一旦开始工作,就可以加载 Linux 系统的 vmlinuz 内核文件了。 5. Linux vmlinuz的生成 1)由Linux 编译生成的 bzImage 文件复制而来,存放在 /boot 目录下 2)bzImage 由 arch/x86/boot/Makefile 编译而来,依赖 setup.bin和vmlinux.bin两个。 3)setup.bin 由 /arch/x86/boot/ 目录下的文件编译生成 4)arch/x86/boot/compressed 目录 编译生成 vmlinux.bin过程总结:Linux 的 kbuild(内核编译)系统会递归进入到每个目录,由该目录下的 Makefile 决定要编译的文件。每个目录编译生成一个 built-in.o,所有的 built-in.o最终链接生成一个 vmlinux 文件最终压缩成 vmlinux.bin.gz,最终由mkpiggy 生成 vmlinux。 二、思考题 为什么要用 C 代码 mkpiggy 程序生成 piggy.S 文件,并包含 vmlinux.bin.gz 文件呢? ==》通过main函数传入的可变参数可以根据需要灵活扩展piggy.S的内容?

    作者回复: 666666

    2022-06-19
    4
  • pedro
    工具生成方式灵活,支持多种配置,且能满足各种场景下的需求~

    作者回复: 是的 对头

    2021-06-09
    3
  • springXu
    程序来生成汇编代码,这个是有多种配置让使用者根据自己的需求来生成。比如vmlinuz.bin压缩的方式的不同又或者是cpu的指令不同。 产生的汇编代码也不同。 另外Cosmos.eki的生成过程能有个说明不?

    作者回复: 我课程中有生成eki文件的方式

    2021-06-09
    4
    2
  • blentle
    不管肚子多少遍启动流程,还是记不住各种地址,除了0×7c00,哈哈

    作者回复: 哈哈 这个地址 精典

    2021-06-10
    1
  • Fan
    又学习了一遍启动流程。😂

    编辑回复: 来了老铁,启动流程,常看常新~

    2021-06-09
    1
收起评论
显示
设置
留言
14
收藏
沉浸
阅读
分享
手机端
快捷键
回顶部