查看“Boot Sequence”的源代码
←
Boot Sequence
跳到导航
跳到搜索
因为以下原因,您没有权限编辑本页:
您请求的操作仅限属于该用户组的用户执行:
用户
您可以查看和复制此页面的源代码。
== POST == 当计算机被打开或重置时,它会运行一系列被称为POST-'''P'''ower-'''O'''n '''S'''elf-'''T'''est的上电自我检测过程。 这一过程的最终结果是按照固件配置的顺序来定位可引导设备,如软盘、CD-ROM或硬盘。 == 主引导记录(Master Boot Record - MBR) == (传统)BIOS检查可引导设备的引导签名,找到所谓的magic number。 引导签名位于引导扇区(扇区号0)中,它分别在字节偏移量510和511处包含字节序列0x55、0xAA。 当BIOS找到这样一个引导扇区时,它被加载到内存中的<tt>0x0000:0x7c00</tt>(段0,地址0x7c00)。 然而,一些BIOS加载到<tt>0x7c0:0x0000</tt>(段0x07c0,偏移量0),这解析为相同的物理地址。 一个好的实践是在启动扇区的一开始就强制执行CS:IP。 然后将执行转移到新加载的引导记录(boot record)。 在软盘上,引导记录的所有512字节(保存最后两个签名字节)包含可执行代码。 在硬盘驱动器上,[[MBR(x86)|主引导记录]](MBR)在偏移量0x0000-0x01bd处保存可执行代码,然后是四个[[Partition table | 主分区]]的表项,每个项使用十六个字节(0x01be-0x01fd)和两个字节的签名(0x01fe-0x01ff)。 == 早期运行环境 == 这种早期执行环境是高度由具体实现定义的,这意味着特定BIOS的实现。 ''永远不''对寄存器的内容做任何假设:它们可能被初始化为0,但也可能包含虚假值。 这包括FLAGS寄存器和SP寄存器,你可能也没有有效的堆栈! 唯一可以确定的是,DL寄存器保存了加载引导代码的驱动代码。 CPU当前处于[[Real Mode|实模式]]。 (除非你运行的是一种罕见的BIOS,它认为激活[[Protected Mode|保护模式]]是在帮你的忙。 这意味着你不仅必须编写代码来激活任何“其他”硬件上的保护模式,而且还应为激活的保护模式添加测试条件。) == 内核 == 最后,引导加载程序将内核加载到内存中,并将控制权传递给它。 == 加载内核 == 现在我们知道引导记录要将内核加载起来,让我们看看如何加载。 如果从硬盘引导,则只有446字节可用于引导记录。 查看以下内核映像运行之前要做的任务清单,你会发现这点空间并不多: * 确定从哪个分区启动(通过查找活动分区,或通过向用户提供可供选择的已安装操作系统); * 确定你的内核映像在引导分区上的位置 (通过解释文件系统或从固定位置加载映像); * 将内核映像加载到内存中(需要基本磁盘I/O); * 启用保护模式; * 为内核准备运行时环境 (例如设置堆栈空间); 你不必按此顺序执行操作,但在调用<tt>kmain()</tt>之前(译者注:kmain指自制内核的入口函数),必须完成所有这些操作。 更糟糕的是,GCC只生成受保护模式的可执行文件,因此写代码搭建这个早期运行环境是[[C#Things C can't do|C做不到的事情]]之一。 有几种方法可以解决此问题: * '''Geek loading''': 技巧型载入,将上述列表中的所有内容都压缩到引导记录中。 这几乎是不可能的,并且也许不能为特殊情况处理或有用的错误消息留出空间。 * '''One-stage loading''': 单阶段载入,编写一个用于切换的存根程序,并将其链接到内核映像前面。 引导记录加载内核映像(低于1mb内存,因为在实模式下,这是内存上限!),跳入存根(Stub),存根切换到保护模式和运行时准备,再跳入内核。 * '''Two-stage loading''': 两阶段载入,编写一个 “单独” 存根程序,该程序加载到1mb内存标记以下,并执行上述列表中的所有操作。 === 传统方式 === 传统上,MBR将自己重新定位到<tt>0x0000:0x0600</tt>,从分区表确定活动分区,将该分区的第一个扇区(“分区启动记录”)加载到<tt>0x0000:0x7c00</tt>,并跳到该地址。 这被称为“链式装载”。如果你希望自己编写的引导记录能够进行双重引导(例如Windows),则应该模拟这种行为。 === 捷径 === 除非你真的想[[Rolling Your Own Bootloader|弄一个自制引导加载程序]](包含记录record或存根stubs)以获得教学价值,否则我们建议使用现成的[[:Category:bootloaders|引导加载程序]]。 最突出的是[[GRUB]],这是一种two-stage bootloader,它不仅提供具有链式加载功能的引导菜单,而且将早期运行环境初始化为定义良好的状态(包括[[Protected Mode|保护模式]],并从BIOS读取各种感兴趣的信息),可以将通用可执行文件作为内核映像加载(而不像大多数其他引导加载程序那样需要简单二进制文件),支持可选的内核模块、各种文件系统,如果<tt>./configure</tt>正确配置还能支持[[Diskless Booting|无盘引导]]。 === 其他一些方法 === 有许多可能的变体可以引导系统。以下是方法列表,但可能还有更多方法: * 你可以使用一个未使用的分区并加载阶段二的原始映像(raw) * 你可以将阶段二放在MBR和第一个分区开头之间 * 你可以(像Lilo那样)编写一个内核文件,然后使用工具检测扇区(或簇)。然后让阶段一从列表中加载扇区。 * DOS和Windows是这样做的: 创建一个空文件系统 (对其进行格式化),然后将内核放置在第一个文件中,将shell放置在空根目录的第二个文件中。 因此,加载程序只需在根目录中加载第一个条目,然后再加载第二个条目。 * 旧Linux是从软盘启动的。 第一个扇区(“boot”)以“原始内容”(不带文件系统)模式加载第二个阶段 (第二阶段是 “setup”,位于 “boot” 后面的扇区中) 第二阶段设置好系统(视频模式、内存映射等),然后加载真实的内核映像(打包在tgz/bz中)。 * 几年前,有一个引导加载程序(称为“nuni”),它能切换到保护模式并加载一个文件,同时把所有这些都实现在一个引导扇区中 == 另见 == === 外部链接 === * [http://duartes.org/gustavo/blog/post/how-computers-boot-up Jun 2008: How Computers Boot Up] by Gustavo Duarte. * [http://duartes.org/gustavo/blog/post/kernel-boot-process Jun 2008:The Kernel Boot Process] by Gustavo Duarte. * IBM developerWorks' [https://developer.ibm.com/technologies/linux/articles/l-linuxboot/ Inside the Linux boot process] a very good, illustrated overview from BIOS to userspace. [[Category:Bootloaders]] [[Category:X86]] [[de:Bootprozess auf x86]]
返回至“
Boot Sequence
”。
导航菜单
个人工具
登录
命名空间
页面
讨论
变体
已展开
已折叠
查看
阅读
查看源代码
查看历史
更多
已展开
已折叠
搜索
导航
首页
最近更改
随机页面
MediaWiki帮助
工具
链入页面
相关更改
特殊页面
页面信息