Linux 系统开机加电后发生了什么?
扫描二维码
随时随地手机看文章
-
POST自检
-
BIOS(Boot Sequence)
-
加载对应引导上的MBR(bootloader)
-
主引导设置加载其BootLoader
启动BIOS,准备实模式下的中断向量表和中断服务程序
电脑启动后,CPU逻辑电路被设计为只能运行内存中的程序,没有能力直接运行存在于软盘或硬盘中的操作系统,如果想要运行,必须要加载到内存(RAM)中。
POST自检
BIOS的第一步动作就是进行 上电自检(POST)
初始化设备
BIOS的第二步动作就是 枚举本地设备并初始化
BIOS-runtime服务按照boot启动顺序搜索设备,寻找BBR
由于BIOS功能使用上的不同,它由两个部分组成:POST和runtime服务。POST完成后,它将从存储器中被清除,但是BIOS runtime服务会被保留,用于目标操作系统。
引导操作系统内核并为保护模式做准备
位于MBR中的主 boot loader 是一个512字节的镜像,其中不仅包含了 bootload 程序代码,还包含了一个小的分区表。
把第一阶段和第二阶段的 boot loaders 联合起来,就是在x86个人电脑中,我们所说的 linux loader(LILO)或者 GRand Unified Bootloader(GRUB)。由于 GRUB 修正了一些 LILO 中存在的缺陷,因此下面就让我们来看看 GRUB(如果你希望得到更多的关于 GRUB,LILO 和与之相关话题的讨论资源,请见文后的参考资料)在次 boot loader 存在与内存中后,就可以对文件系统进行查询了,同时将默认的内核镜像以及初始化内存盘镜像也被加载到内存中。
对于 GRUB 来说,一个比较好的方面就是它包含了 linux 文件系统的知识。与LILO使用裸扇区不同的是,GRUB 能够从 ext2 或者 ext3 文件系统中加载 linux 内核。它是通过将本来两阶段的 boot loader 转换成三个阶段的 boot loader。在第一阶段(MBR)中会启动 stage1.5 的 boot loader 来理解 linux 内核镜像中的特殊的文件系统格式,例如,reiserfs_stage1-5(用于从reiserf日志文件系统中进行加载)或 e2fs stage1_5 (用于从wxt2或ext3文件系统进行加载)。当 stage1.5 的 boot loader 被加载并运行时,stage2 的 boot loader 才能被加载。当 stage2 被加载时,GRUB能根据请求的情况显示一个可选内核的清单(在 /etc/grub.conf 中进行定义,同时还有几个软符号链接 /etc/grub/menu.lst 和 /etc/grub.conf)。你可以选择一个内核,修改其附加的内核参数。同时,你可以选择使用命令行的shell来对启动过程进行更深层次的手工控制。
加载内核并从实模式转换为保护模式
当内核映像被加载到内存中(加载过程仍然用int 0x13中断向量),并且次引导加载程序释放控制权之后,内核阶段就开始了。
加载内核镜像
内核映像并不是一个可执行的内核,而是一个压缩过的内核映像。通常它是一个 zImage(压缩映像,小于 512KB)或一个 bzImage(较大的压缩映像,大于 512KB),它是提前使用 zlib 进行压缩过的。在这个内核映像前面是一个例程,它实现少量硬件设置,并对内核映像中包含的内核进行解压,然后将其放入高端内存中,如果有初始 RAM 磁盘映像,就会将它移动到内存中,并标明以后使用。然后该例程会调用内核,并开始启动内核引导的过程。
进入保护模式并初始化
-
进入保护模式
-
设置中断描述附表和全局描述符表
-
创建了内存分页机制
启动内核
-
start_kernel启动内核
-
创建init进程
BIOS阶段–准备实模式下的中断向量表和中断服务程序
BIOS是什么
上个世纪70年代初,”只读内存”(read-only memory,缩写为ROM)发明,开机程序被刷入ROM芯片,计算机通电后,第一件事就是读取它。计算机,启动这块芯片里的程序叫做”基本輸出輸入系統”(Basic Input/Output System),简称为BIOS。
BIOS存储的信息
BIOS芯片中主要存放:
-
自诊断程序:通过读取CMOSRAM中的内容识别硬件配置,并对其进行自检和初始化;
-
CMOS设置程序:引导过程中,用特殊热键启动,进行设置后,存入CMOS RAM中;
-
系统自举装载程序:在自检成功后将磁盘相对0道0扇区上的引导程序装入内存,让其运行以装入DOS系统;
-
主要I/O设备的驱动程序和中断服务:由于BIOS直接和系统硬件资源打交道,因此总是针对某一类型的硬件系统,而各种硬件系统又各有不同,所以存在各种不同种类的BIOS,随着硬件技术的发展,同一种BIOS也先后出现了不同的版本,新版本的BIOS比起老版本来说,功能更强。
BIOS是如何启动的
CPU硬件逻辑设计为在加电瞬间强行将CS值置为0XF000,IP为0XFFF0,这样CS:IP就指向0XFFFF0这个位置,这个位置正是BIOS程序的入口地址。
BIOS需要在内存中加载中断向量表和中断服务程序
BIOS程序被固化在计算机主机板上的一块很小的ROM芯片里。现在CS:IP已经指向了0XFFFF0这个位置,意味着BIOS开始启动。随着BIOS程序的执行,屏幕上会显示显卡的信息,内存的信息,说明BIOS程序在检测显卡,内存,这个就是POST开机自检期间,有一项对启动操作系统至关重要的工作,那就是BIOS在内存中建立中断向量表和中断服务程序
BIOS阶段的工作
POST开机自检
BIOS程序首先检查,计算机硬件能否满足运行的基本条件,这叫做”硬件自检”(Power-On Self-Test),缩写为POST。如果硬件出现问题,主板会发出不同含义的蜂鸣,启动中止。如果没有问题,屏幕就会显示出CPU、内存、硬盘等信息。
-
对于严重故障(致命性故障)则停机,此时由于各种初始化操作还没完成,不能给出任何提示或信号;
-
对于非严重故障则给出提示或声音报警信号,等待用户处理),如果没有故障,POST完整自己的接力任务,将尾部工作交接给BIOS处理
加载BIOS
BIOS把控制权转交给下一阶段的启动程序。
引导操作系统
硬件自检完成后,我们期望能否启动操作系统,但是问题出来了
-
操作系统存放在哪?
-
BIOS如何找到操作系统?
-
BIOS如何加载操作系统?
背景知识
多操作系统时的启动顺序
主引导记录 MBR
位于MBR中的主boot loader是一个512字节的镜像,其中不仅包含了程序代码,还包含了一个小的分区表。
-
第1-446字节:调用操作系统的机器码。
-
第447-510字节:分区表(Partition table)。
-
第511-512字节:主引导记录签名(0x55和0xAA)。
分区表
硬盘分区有很多好处。考虑到每个区可以安装不同的操作系统,”主引导记录”因此必须知道将控制权转交给哪个区。分区表的长度只有64个字节,里面又分成四项,每项16个字节。所以,一个硬盘最多只能分四个一级分区,又叫做“主分区”。
-
第1个字节:如果为0x80,就表示该主分区是激活分区,控制权要转交给这个分区。四个主分区里面只能有一个是激活的。
-
第2-4个字节:主分区第一个扇区的物理位置(柱面、磁头、扇区号等等)。
-
第5个字节:主分区类型。
-
第6-8个字节:主分区最后一个扇区的物理位置。
-
第9-12字节:该主分区第一个扇区的逻辑地址。
-
第13-16字节:主分区的扇区总数。
-
一是提高每个扇区的字节数,
-
二是增加扇区总数。
引导操作系统的过程
由硬盘启动时,BIOS通常是转向第一块硬盘的第一个扇区,即主引导记录(MBR)。装载GRUB和操作系统的过程,包括以下几个操作步骤:
加载主引导加载程序-基本装载程序
众所周知,硬盘上第0磁道第一个扇区被称为MBR,也就是Master Boot Record,即主引导记录,它的大小是512字节,别看地方不大,可里面却存放了预启动信息、分区表信息。
MBR程序只是找到只是硬盘分区内最前面的446个字节的Boot Loader,然后查找相关配置和定义。然后将控制权交给主引导代码。主引导代码的任务包括
-
扫描分区表,找到一个激活(可引导)分区;
-
找到激活分区的起始扇区;
-
将激活分区的引导扇区装载到内存7C00处;
-
将控制权交给引导扇区代码;
加载次引导记载程序–高级装载程序bootload如GRUB
系统读取内存中的grub配置信息(一般为menu.lst或grub.lst),并依照此配置信息来启动不同的操作系统。
为什么这么复杂
早期的操作系统并没有那么复杂,当然bootload也没有那么多功能,但是如今我们的操作系统越来越复杂,bootload也越来越庞大,而且如今在一台电脑上安装多系统变得那么平常,因此之前简单的bootload已经无法满足这些功能。
-
提供菜单:用户可以选择不同的开机选项,这也是多重引导的重要功能
-
载入内核文件:直接指向可开机的程序段来开始操作系统。
-
转交其他Loader:将引导加载功能转交给其他loader负责
-
每个分区都有自己的启动扇区
-
系统分区为第一及第二分区
-
实际可开机的内核文件是放置到各分区内的
-
loader只会认识自己的系统分区内的可开机内核文件,以及其他的Loader而已
-
loader可直接指向或者是间接将管理权交给另一个管理程序
现在想一下,为什么人家常说:”如果要安装多重引导,最好先安装Windows再安装Linux呢“?
这是因为Linux在安装时,你可以选择将引导加载程序安装在MBR或个别分区的启动扇区,而且Linux的Loader可以手动设置菜单,所以你可以在Linux的Boot Loader里面加入Windows开机选项
Windows在安装的时候,他的安装程序会主动覆盖掉MBR以及自己所在分区的启动扇区,你没有选择的机会,而且他没有让我们自己选择菜单功能
加载操作系统内核
用户选择要加载的内核之后,次引导加载程序(GRUB)就会根据/boot/grub.conf配置文件中所设置的信息,从/boot/所在的分区上读取Linux内核映像,然后把内核映像加载到内存中并把控制权交给Linux内核。
-
检测硬件
-
解压缩自己并安装必要驱动
-
初始化与文件系统相关的虚拟设备,LVM或RAID
-
装载根文件系统,挂在根目录下面
-
完成之后,linux在进程空间里面加载init程序,下面轮到init干活
-
0:关机
-
1:单用户模式
-
2:无网络支持的多用户模式
-
3:有网络支持的多用户模式
-
4:保留,未使用
-
5:有网络支持有X-Window支持的多用户模式
-
6:重新引导系统,即重启
init进程执行rc.sysinit
在设定了运行等级后,Linux系统执行的第一个用户层文件就是/etc/rc.d/rc.sysinit脚本程序,它做的工作非常多,包括设定PATH、设定网络配置(/etc/sysconfig/network)、启动swap分区、设定/proc等等。如果你有兴趣,可以到/etc/rc.d中查看一下rc.sysinit文件,里面的脚本够你看几天的
启动内核模块
具体是依据/etc/modules.conf文件或/etc/modules.d目录下的文件来装载内核模块。
执行不同运行级别的脚本程序
根据运行级别的不同,系统会运行rc0.d到rc6.d中的相应的脚本程序,来完成相应的初始化工作和启动相应的服务。
执行/etc/rc.d/rc.local
你如果打开了此文件,里面有一句话,读过之后,你就会对此命令的作用一目了然:
# You can put your own initialization stuff in here if you don’t
# want to do the full Sys V style init stuff.
rc.local就是在一切初始化工作后,Linux留给用户进行个性化的地方。你可以把你想设置和启动的东西放到这里。
执行/bin/login程序,进入登录状态
此时,系统已经进入到了等待用户输入username和password的时候了,你已经可以用自己的帐号登入系统了。