Linux引导过程
早期时,启动一台计算机意味着要给计算机喂一条包含引导程序的纸带,或者手工使用前端面板地址/数据/控制开关来加载引导程序。尽管目前的计算机已经装备了很多工具来简化引导过程,但是这一切并没有对整个过程进行必要的简化。
让我们先从高级的视角来查看 Linux 引导过程,这样就可以看到整个过程的全貌了。然后将回顾一下在各个步骤到底发生了什么。在整个过程中,参考一下内核源代码可以帮助我们更好地了解内核源代码树,并在以后对其进行深入分析。
概述
图 1 是我们在 20,000 英尺的高度看到的视图。
图 1. Linux 引导过程在 20,000 英尺处的视图
当 系统首次引导时,或系统被重置时,处理器会执行一个位于已知位置处的代码。在个人计算机(PC)中,这个位置在基本输入/输出系统(BIOS)中,它保存 在主板上的闪存中。嵌入式系统中的中央处理单元(CPU)会调用这个重置向量来启动一个位于闪存/ROM 中的已知地址处的程序。在这两种情况下,结果都是相同的。因为 PC 提供了很多灵活性,BIOS 必须确定要使用哪个设备来引导系统。稍后我们将详细介绍这个过程。
当找到一个引导设备之后,第一阶段的引导加载程序就被装入 RAM 并执行。这个引导加载程序在大小上小于 512 字节(一个扇区),其作用是加载第二阶段的引导加载程序。
当第二阶段的引导加载程序被装入 RAM 并执行时,通常会显示一个动画屏幕,并将 Linux 和一个可选的初始 RAM 磁盘(临时根文件系统)加载到内存中。在加载映像时,第二阶段的引导加载程序就会将控制权交给内核映像,然后内核就可以进行解压和初始化了。在这个阶段 中,第二阶段的引导加载程序会检测系统硬件、枚举系统链接的硬件设备、挂载根设备,然后加载必要的内核模块。完成这些操作之后启动第一个用户空间程序(init
),并执行高级系统初始化工作。
这就是 Linux 引导的整个过程。现在让我们深入挖掘一下这个过程,并深入研究一下 Linux 引导过程的一些详细信息。
系统启动
系 统启动阶段依赖于引导 Linux 系统上的硬件。在嵌入式平台中,当系统加电或重置时,会使用一个启动环境。这方面的例子包括 U-Boot、RedBoot 和 Lucent 的 MicroMonitor。嵌入式平台通常都是与引导监视器搭配销售的。这些程序位于目标硬件上的闪存中的某一段特殊区域,它们提供了将 Linux 内核映像下载到闪存并继续执行的方法。除了可以存储并引导 Linux 映像之外,这些引导监视器还执行一定级别的系统测试和硬件初始化过程。在嵌入式平台中,这些引导监视器通常会涉及第一阶段和第二阶段的引导加载程序。
提取 MBR 的信息
要查看 MBR 的内容,请使用下面的命令:
# dd if=/dev/hda of=mbr.bin bs=512 count=1 # od -xa mbr.bin
这个 dd
命令需要以 root 用户的身份运行,它从 /dev/hda(第一个 IDE 盘) 上读取前 512 个字节的内容,并将其写入 mbr.bin
文件中。od
命令会以十六进制和 ASCII 码格式打印这个二进制文件的内容。
在 PC 中,引导 Linux 是从 BIOS 中的地址 0xFFFF0 处开始的。BIOS 的第一个步骤是加电自检(POST)。POST 的工作是对硬件进行检测。BIOS 的第二个步骤是进行本地设备的枚举和初始化。
给定 BIOS 功能的不同用法之后,BIOS 由两部分组成:POST 代码和运行时服务。当 POST 完成之后,它被从内存中清理了出来,但是 BIOS 运行时服务依然保留在内存中,目标操作系统可以使用这些服务。
要引导一个操作系统,BIOS 运行时会按照 CMOS 的设置定义的顺序来搜索处于活动状态并且可以引导的设备。引导设备可以是软盘、CD-ROM、硬盘上的某个分区、网络上的某个设备,甚至是 USB 闪存。
通常,Linux 都是从硬盘上引导的,其中主引导记录(MBR)中包含主引导加载程序。MBR 是一个 512 字节大小的扇区,位于磁盘上的第一个扇区中(0 道 0 柱面 1 扇区)。当 MBR 被加载到 RAM 中之后,BIOS 就会将控制权交给 MBR。
第一阶段引导加载程序
MBR 中的主引导加载程序是一个 512 字节大小的映像,其中包含程序代码和一个小分区表(参见图 2)。前 446 个字节是主引导加载程序,其中包含可执行代码和错误消息文本。接下来的 64 个字节是分区表,其中包含 4 个分区的记录(每个记录的大小是 16 个字节)。MBR 以两个特殊数字的字节(0xAA55)结束。这个数字会用来进行 MBR 的有效性检查。
图 2. MBR 剖析
主 引导加载程序的工作是查找并加载次引导加载程序(第二阶段)。它是通过在分区表中查找一个活动分区来实现这种功能的。当找到一个活动分区时,它会扫描分区 表中的其他分区,以确保它们都不是活动的。当这个过程验证完成之后,就将活动分区的引导记录从这个设备中读入 RAM 中并执行它。
第二阶段引导加载程序
次引导加载程序(第二阶段引导加载程序)可以更形象地称为内核加载程序。这个阶段的任务是加载 Linux 内核和可选的初始 RAM 磁盘。
GRUB 阶段引导加载程序
/boot/grub
目录中包含了 stage1
、stage1.5
和 stage2
引导加载程序,以及很多其他加载程序(例如,CR-ROM 使用的是 iso9660_stage_1_5
)。
在 x86 PC 环境中,第一阶段和第二阶段的引导加载程序一起称为 Linux Loader(LILO)或 GRand Unified Bootloader(GRUB)。由于 LILO 有一些缺点,而 GRUB 克服了这些缺点,因此下面让我们就来看一下 GRUB。(有关 GRUB、LILO 和相关主题的更多内容,请参阅本文后面的 参考资料 部分的内容。)
关 于 GRUB,很好的一件事情是它包含了有关 Linux 文件系统的知识。GRUB 不像 LILO 一样使用裸扇区,而是可以从 ext2 或 ext3 文件系统中加载 Linux 内核。它是通过将两阶段的引导加载程序转换成三阶段的引导加载程序来实现这项功能的。阶段 1 (MBR)引导了一个阶段 1.5 的引导加载程序,它可以理解包含 Linux 内核映像的特殊文件系统。这方面的例子包括 reiserfs_stage1_5
(要从 Reiser 日志文件系统上进行加载)或 e2fs_stage1_5
(要从 ext2 或 ext3 文件系统上进行加载)。当阶段 1.5 的引导加载程序被加载并运行时,阶段 2 的引导加载程序就可以进行加载了。
当阶段 2 加载之后,GRUB 就可以在请求时显示可用内核列表(在 /etc/grub.conf
中进行定义,同时还有几个软符号链接 /etc/grub/menu.lst
和 /etc/grub.conf
)。我们可以选择内核甚至修改附加内核参数。另外,我们也可以使用一个命令行的 shell 对引导过程进行高级手工控制。
将第二阶段的引导加载程序加载到内存中之后,就可以对文件系统进行查询了,并将默认的内核映像和 initrd
映像加载到内存中。当这些映像文件准备好之后,阶段 2 的引导加载程序就可以调用内核映像了。
内核
GRUB 中的手工引导
在 GRUB 命令行中,我们可以使用 initrd
映像引导一个特定的内核,方法如下:
grub> kernel /bzImage-2.6.14.2
[Linux-bzImage, setup=0x1400, size=0x29672e]
grub> initrd /initrd-2.6.14.2.img
[Linux-initrd @ 0x5f13000, 0xcc199 bytes]
grub> boot
Uncompressing Linux... Ok, booting the kernel.
如果您不知道要引导的内核的名称,只需使用斜线(/)然后按下 Tab 键即可。GRUB 会显示内核和 initrd
映像列表。
当
内核映像被加载到内存中,并且阶段 2
的引导加载程序释放控制权之后,内核阶段就开始了。内核映像并不是一个可执行的内核,而是一个压缩过的内核映像。通常它是一个
zImage(压缩映像,小于 512KB)或一个 bzImage(较大的压缩映像,大于 512KB),它是提前使用 zlib
进行压缩过的。在这个内核映像前面是一个例程,它实现少量硬件设置,并对内核映像中包含的内核进行解压,然后将其放入高端内存中,如果有初始 RAM
磁盘映像,就会将它移动到内存中,并标明以后使用。然后该例程会调用内核,并开始启动内核引导的过程。
当 bzImage(用于 i386 映像)被调用时,我们从 ./arch/i386/boot/head.S
的 start
汇编例程开始执行(主要流程图请参看图 3)。这个例程会执行一些基本的硬件设置,并调用 ./arch/i386/boot/compressed/head.S
中的 startup_32
例程。此例程会设置一个基本的环境(堆栈等),并清除 Block Started by Symbol(BSS)。然后调用一个叫做 decompress_kernel
的 C 函数(在 ./arch/i386/boot/compressed/misc.c
中)来解压内核。当内核被解压到内存中之后,就可以调用它了。这是另外一个 startup_32
函数,但是这个函数在 ./arch/i386/kernel/head.S
中。
在这个新的 startup_32
函数(也称为清除程序或进程 0)中,会对页表进行初始化,并启用内存分页功能。然后会为任何可选的浮点单元(FPU)检测 CPU 的类型,并将其存储起来供以后使用。然后调用 start_kernel
函数(在 init/main.c
中),它会将您带入与体系结构无关的 Linux 内核部分。实际上,这就是 Linux 内核的 main
函数。
图 3. Linux 内核 i386 引导的主要函数流程
通过调用 start_kernel
,会调用一系列初始化函数来设置中断,执行进一步的内存配置,并加载初始 RAM 磁盘。最后,要调用 kernel_thread
(在 arch/i386/kernel/process.c
中)来启动 init
函数,这是第一个用户空间进程(user-space process)。最后,启动空任务,现在调度器就可以接管控制权了(在调用 cpu_idle
之后)。通过启用中断,抢占式的调度器就可以周期性地接管控制权,从而提供多任务处理能力。
在内核引导过程中,初始 RAM 磁盘(initrd
)是由阶段 2 引导加载程序加载到内存中的,它会被复制到 RAM 中并挂载到系统上。这个 initrd
会作为 RAM 中的临时根文件系统使用,并允许内核在没有挂载任何物理磁盘的情况下完整地实现引导。由于与外围设备进行交互所需要的模块可能是 initrd
的一部分,因此内核可以非常小,但是仍然需要支持大量可能的硬件配置。在内核引导之后,就可以正式装备根文件系统了(通过 pivot_root
):此时会将 initrd
根文件系统卸载掉,并挂载真正的根文件系统。
decompress_kernel 输出
函数 decompress_kernel
就是显示我们通常看到的解压消息的地方:
Uncompressing Linux... Ok, booting the kernel.
initrd
函数让我们可以创建一个小型的 Linux 内核,其中包括作为可加载模块编译的驱动程序。这些可加载的模块为内核提供了访问磁盘和磁盘上的文件系统的方法,并为其他硬件提供了驱动程序。由于根文件系统是磁盘上的一个文件系统,因此 initrd
函数会提供一种启动方法来获得对磁盘的访问,并挂载真正的根文件系统。在一个没有硬盘的嵌入式环境中,initrd
可以是最终的根文件系统,或者也可以通过网络文件系统(NFS)来挂载最终的根文件系统。
Init
当内核被引导并进行初始化之后,内核就可以启动自己的第一个用户空间应用程序了。这是第一个调用的使用标准 C 库编译的程序。在此之前,还没有执行任何标准的 C 应用程序。
在桌面 Linux 系统上,第一个启动的程序通常是 /sbin/init
。但是这不是一定的。很少有嵌入式系统会需要使用 init
所提供的丰富初始化功能(这是通过 /etc/inittab
进行配置的)。在很多情况下,我们可以调用一个简单的 shell 脚本来启动必需的嵌入式应用程序。
结束语
与 Linux 本身非常类似,Linux
的引导过程也非常灵活,可以支持众多的处理器和硬件平台。最初,加载引导加载程序提供了一种简单的方法,不用任何花架子就可以引导 Linux。LILO
引导加载程序对引导能力进行了扩充,但是它却缺少文件系统的感知能力。最新一代的引导加载程序,例如 GRUB,允许 Linux 从一些文件系统(从
Minix 到 Reise)上进行引导。
参考资料
学习
- 您可以参阅本文在 developerWorks 全球站点上的 英文原文 。
- 请查看 Disk
Geometry 页面来理解磁盘及其结构。您会发现有关磁盘的有用属性。 - live CD 是一个可以从 CD 或 DVD 上引导的操作系统,它不需要使用硬盘。
- “引导加载程序之争:了解 LILO 和 GRUB”(developerWorks,2005 年 8 月)详细介绍了 LILO 和 GRUB 引导加载程序。
- LILO 是 GRUB 的先驱,但是我们可能发现它依然可以引导 Linux。
- 在 Debian Linux Kernel Project 中,我们可以找到更多有关 Linux 内核、引导和嵌入式开发的信息。
- 在 developerWorks Linux 专区 中可以找到为 Linux 开发人员准备的更多资源。
- 随时关注 developerWorks 技术事件和网络广播。
获得产品和技术
- GNU GRUB 是一个具有众多选项和灵活性的引导 shell。
- LinuxBIOS 是 BIOS 的一个替代品。LinuxBIOS 不但可以引导 Linux,而且它本身就是一个压缩的 Linux 内核。
- OpenBIOS 是另一个可移植的 BIOS 项目,可以在很多体系结构上进行操作,例如 x86、Alpha 和 AMD64。
- 在 kernel.org 上可以找到最新的内核树。
- 使用 IBM 试用版软件 改进您的下一个开发项目,从 developerWorks 上可以直接下载这些软件。
讨论
- 通过参与 developerWorks blogs 加入 developerWorks 社区。
Linux引导过程的更多相关文章
- Linux 引导过程内幕
转载:http://www.ibm.com/developerworks/cn/linux/l-linuxboot/index.html 从主引导记录到第一个用户空间应用程序的指导 引导 Linu ...
- 【转】Linux 高级的视角来查看Linux引导过程
[原文]https://www.toutiao.com/i6594210975480545800/ 1.概述 图 1 是我们在20,000 英尺的高度看到的视图. 当系统首次引导时,或系统被重置时,处 ...
- Linux引导过程和服务过程
目录 一.Linux操作系统引导过程 1.1.开机自检 1.2.MBR引导 1.3.GRUB菜单 1.4.加载Linux内核 1.5.init进程初始化 二.系统初始化进程 2.1.init进程 2. ...
- Linux引导过程与服务控制
一:系统引导流程: 开机自检(BIOS)-->MBR引导-->GRUB菜单-->加载内核(kernel)-->init进程初始化 二:系统引导级别: 0 poweroff.t ...
- Linux引导过程!(重点)
1.开机自检:服务器开机后,将根据主板BIOS (基本输入系统),中的设置对CPU .内存.显卡.键盘等设备进行初步检测,并初始化部分硬件. 2.MBR 引导:当从本机硬盘中启动系统时,首先根据硬盘中 ...
- Linux学习笔记之Linux启动引导过程
早期时,启动一台计算机意味着要给计算机喂一条包含引导程序的纸带,或者手工使用前端面板地址/数据/控制开关来加载引导程序.尽管目前的计算机已经装备了很多工具来简化引导过程,但是这一切并没有对整个过程进行 ...
- Linux学习笔记:系统启动引导过程
Linux系统启动引导过程 近期发现自己在仅仅是掌握上有几个比較硬的伤: 一.知识体系碎片,比方Linux,这学点那学点,结果没有成体系,串不起来: 二.记忆时间短暂,非常多的内容学了就忘,最后的结果 ...
- Linux引导启动程序 - boot
主要描述 boot/目录中的三个汇编代码文件,见列表 3-1 所示.正如在前一章中提到的,这三个 文件虽然都是汇编程序,但却使用了两种语法格式.bootsect.s 和 setup.s 采用近似于 I ...
- [svc]linux启动过程及级别
Unix目录结构的来历 Linux 的启动流程 Linux 引导过程内幕 嵌入式系统 Boot Loader 技术内幕 centos6使用chkconfig治理服务和其原理 centos7的服务治理- ...
随机推荐
- CC3100BoosterPack和CC31XXEMUBOOST板子的测试
1. 先测试右边的CC3100BoosterPack,测试发现LDO坏了,无法输出3.3V,所以只能用左边的板子供电. 2. 插上CC31XXEMUBOOST板子的J1,两个板子插在一起,等待驱动安装 ...
- html5学得好不好,看掌握多少标签
html5学得好不好,看掌握多少标签 已回复 会员ID:wi701329 保密 62岁 时间:2016-06-28 06:52:49 html5你了解了多少?如果你还是入门阶段的话,或者还是一知半解的 ...
- 3,SQL语句及数据库优化
1,统一SQL语句的写法 对于以下两句SQL语句,程序员认为是相同的,数据库查询优化器认为是不同的. 所以封装成复用方法,用标准模板来控制. select*from dual select*Fr ...
- IOException: win32 io returned 267. Path:
unity3d在导出android项目时出现了这个错误,找了一圈也没找到原因,最后把项目名中空格去掉后OK了,坑啊!!!!
- 每天一个Linux命令(13):apt命令
apt-get和apt-cache命令是Debian Linux发行版中的APT软件包管理工具.所有基于Debian的发行都使用这个包管理系统.deb包可以把一个应用的文件包在一起,大体就如同Wind ...
- 使用IDEA快速搭建Gradle项目
- C++STL——队列
一.相关定义 原理:queue 队列也是一个线性存储表,元素数据的插入在表的一端进行,在另一端删除,从而构成了一个先进先出FIFO(First In First Out)表. 队头&队尾:插入 ...
- 怎么设置table(表格)手机端自适应宽度
我们在wordpress文章页面经常会用到表格,有些是从其他网页或者文档复制粘贴过来的,在电脑设备网页上都能很好的展示,但是在移动设备上或者低分辨率设备上却经常撑破列宽,很是影响美观和客户体验.这里就 ...
- SQL Server 部署CLR程序集错误`6218`
Visual Studio 2015中开发的SQL Server项目,添加了用户自定义函数,需要部署到SQL Server 2005上, 在部署时报错: (70,1): SQL72014: .Net ...
- 获取src下的文件