关于linux系统的启动流程我们可以按步进行划分为如下:
启动BIOS,准备实模式下的中断向量表和中断服务程序电脑启动后,CPU逻辑电路被设计为只能运行内存中的程序,没有能力直接运行存在于软盘或硬盘中的操作系统,如果想要运行,必须要加载到内存(RAM)中。 BIOS程序被固化在计算机主机板上的一块很小的ROM芯片里。现在CS:IP已经指向了0XFFFF0这个位置,意味着BIOS开始启动。 POST自检BIOS的第一步动作就是进行上电自检(POST) POST的工作是检查硬件设备。随着BIOS程序的执行,屏幕上会显示显卡的信息,内存的信息等, 初始化设备BIOS的第二步动作就是枚举本地设备并初始化 有一项对启动操作系统至关重要的工作,那就是BIOS在内存中建立中断向量表和中断服务程序 BIOS程序在内存最开始的位置(0x00000)用1KB的内存空间(0x00000~0x003FF)构建中断向量表,在紧挨着它的位置用256KB的内存空间构建BIOS数据区(0x00400~0x004FF),并在大约57KB以后得位置(0x0e05b)加载了8KB左右的与中断向量表相应的若干中断服务程序。 中断向量表有256个中断向量,每个中断向量占4个字节,其中两个字节是CS值,两个字节是IP值。每个中断向量都指向一个具体的中断服务程序。 BIOS-runtime服务按照boot启动顺序搜索设备,寻找BBR由于BIOS功能使用上的不同,它由两个部分组成:POST和runtime服务。POST完成后,它将从存储器中被清除,但是BIOS runtime服务会被保留,用于目标操作系统。 为了启动操作系统,BIOS的runtime服务将搜索那些激活状态的或是可引导启动的设备,搜索的顺序则由CMOS设置决定(也就是我们平时所谓的在BIOS中设置的启动顺序)。一个软驱,一台光驱,一个硬盘上的分区,网络上的设备甚至一个usb 闪存盘都可以作为一个启动设备。 当然,linux通常是从硬盘启动的。硬盘上的MBR(主启动记录)包含有基本的boot loader,它是一个512字节大小的扇区,位于磁盘的第一个扇区(0磁头0磁道1扇区)。当MBR被装载到RAM中后,BIOS就会将控制权转交给MBR。 引导操作系统内核并为保护模式做准备位于MBR中的主boot loader是一个512字节的镜像,其中不仅包含了bootload程序代码,还包含了一个小的分区表。 最初的446字节是主boot loader,它里面就包含有可执行代码以及错误消息文本。接下来的64字节是分区表,其中包含有四个分区的各自的记录(一个分区占16字节)。MBR通过特殊数字0xAA55(译者注:在电子界中AA55确实是具有传奇色彩的数字,想知道为什么么?将它展开成二进制形式,看看有什么规律)作为两个字节的结束标志。0x55AA同时也是MBR有效的校验确认。 首先对CPU发送int 0x19中断,使CPU运行int 0x19中断对应的中断服务程序,这个中断服务程序的作用就是把软盘第一个扇区的程序加载到内存的指定位置。 主boot loader的工作是寻找并加载次boot loader(内核加载程序) 它通过分析分区表,找出激活分区来完成这个任务,当它找到一个激活分区时,它将继续扫描剩下的分区表中的分区,以便确认他们都是未激活的。 确认完毕后,激活分区的启动记录(次boot loader)从设备中被读到RAM,并被执行。 其中加载过程需要借助BIOS提供的int 0x13中断向量指向的中断服务程序来完成。该程序将软盘第二个扇区开始的4个扇区,即setup.s对应的程序加载至内存的SETUPSEG(0x90200)处。
在次boot loader存在与内存中后,就可以对文件系统进行查询了,同时将默认的内核镜像以及初始化内存盘镜像也被加载到内存中。 一切准备完毕之后,次boot loader就会调用内核镜像,完成操作系统的加载。 加载内核并从实模式转换为保护模式当内核映像被加载到内存中(加载过程仍然用int 0x13中断向量),并且次引导加载程序释放控制权之后,内核阶段就开始了。 加载内核镜像内核映像并不是一个可执行的内核,而是一个压缩过的内核映像。通常它是一个 zImage(压缩映像,小于 512KB)或一个 bzImage(较大的压缩映像,大于 512KB),它是提前使用 zlib 进行压缩过的。在这个内核映像前面是一个例程,它实现少量硬件设置,并对内核映像中包含的内核进行解压,然后将其放入高端内存中,如果有初始 RAM 磁盘映像,就会将它移动到内存中,并标明以后使用。然后该例程会调用内核,并开始启动内核引导的过程。 当 bzImage(用于 i386 映像)被调用时,我们从 ./arch/i386/boot/head.S 的 start 汇编例程开始执行。 这个例程会执行一些基本的硬件设置,并调用 ./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 中。 进入保护模式并初始化
启动内核
BIOS阶段–准备实模式下的中断向量表和中断服务程序BIOS背景知识BIOS是什么上个世纪70年代初,”只读内存”(read-only memory,缩写为ROM)发明,开机程序被刷入ROM芯片,计算机通电后,第一件事就是读取它。 它是一组固化到计算机内主板上一个ROM芯片上的程序,它保存着计算机最重要的基本输入输出的程序、开机后自检程序和系统自启动程序,它可从CMOS中读写系统设置的具体信息。 其主要功能是为计算机提供最底层的、最直接的硬件设置和控制。 BIOS存储的信息BIOS芯片中主要存放:
BIOS:计算机加电自检完成后第一个读取的地方就是就是BIOS(Basic Input Output System,基础输入输出系统),BIOS里面记录了主机板的芯片集与相关设置,如CPU与接口设备的通信频率、启动设备的搜索顺序、硬盘的信息、系统时间、内存信息、时钟信息、PnP特性、外部总线、各种接口设备的I/O地址、已经与CPU通信的IRQ中断信息,所以,启动如果要顺利启动,首先要读取BIOS设置。 计算机会首先加载BIOS信息,BIOS信息是如此的重要,以至于计算机必须在最开始就找到它。 电脑启动后,CPU逻辑电路被设计为只能运行内存中的程序,没有能力直接运行存在于软盘或硬盘中的操作系统,如果想要运行,必须要加载到内存(RAM)中。 BIOS是如何启动的CPU硬件逻辑设计为在加电瞬间强行将CS值置为0XF000,IP为0XFFF0,这样CS:IP就指向0XFFFF0这个位置,这个位置正是BIOS程序的入口地址。 BIOS需要在内存中加载中断向量表和中断服务程序 BIOS程序被固化在计算机主机板上的一块很小的ROM芯片里。现在CS:IP已经指向了0XFFFF0这个位置,意味着BIOS开始启动。随着BIOS程序的执行,屏幕上会显示显卡的信息,内存的信息,说明BIOS程序在检测显卡,内存,这个就是POST开机自检期间,有一项对启动操作系统至关重要的工作,那就是BIOS在内存中建立中断向量表和中断服务程序 BIOS程序在内存最开始的位置(0x00000)用1KB的内存空间(0x00000~0x003FF)构建中断向量表,在紧挨着它的位置用256KB的内存空间构建BIOS数据区(0x00400~0x004FF),并在大约57KB以后得位置(0x0e05b)加载了8KB左右的与中断向量表相应的若干中断服务程序。 中断向量表有256个中断向量,每个中断向量占4个字节,其中两个字节是CS值,两个字节是IP值。每个中断向量都指向一个具体的中断服务程序。 BIOS阶段的工作POST开机自检
电脑主机打开电源的时候,随后会听到滴的一声,系统启动开始了开机自检( 这个过程中主要是检测计算机硬件设备比如:CPU,内存,主板,显卡,CMOS等设备是否有故障存在 如果有硬件故障的话将按两种情况理:
加载BIOSBIOS把控制权转交给下一阶段的启动程序。 这时,BIOS需要知道,”下一阶段的启动程序”具体存放在哪一个设备。也就是说,BIOS需要有一个外部储存设备的排序,排在前面的设备就是优先转交控制权的设备。这种排序叫做”启动顺序”(Boot Sequence)。 在此之后,计算机心里就有谱了,知道应该去读取哪个硬件设备了。 引导操作系统硬件自检完成后,我们期望能否启动操作系统,但是问题出来了 背景知识多操作系统时的启动顺序为了寻找操作系统,BIOS按照”启动顺序”,把控制权转交给排在第一位的储存设备。 这时,计算机读取该设备的第一个扇区,也就是读取最前面的512个字节。 如果这512个字节的最后两个字节是0x55和0xAA,表明这个设备可以用于启动; 如果不是,表明设备不能用于启动,控制权于是被转交给”启动顺序”中的下一个设备。 这最前面的512个字节,就叫做“主引导记录”(Master boot record,缩写为MBR) 主引导记录MBR位于MBR中的主boot loader是一个512字节的镜像,其中不仅包含了程序代码,还包含了一个小的分区表。 最初的446字节是主boot loader,它里面就包含有可执行代码以及错误消息文本。接下来的64字节是分区表,其中包含有四个分区的各自的记录(一个分区占16字节)。MBR通过特殊数字0xAA55(译者注:在电子界中AA55确实是具有传奇色彩的数字,想知道为什么么?将它展开成二进制形式,看看有什么规律)作为两个字节的结束标志。0x55AA同时也是MBR有效的校验确认。 主boot loader的工作是寻找并加载次boot loader。它通过分析分区表,找出激活分区来完成这个任务,当它找到一个激活分区时,它将继续扫描剩下的分区表中的分区,以便确认他们都是未激活的。确认完毕后,激活分区的启动记录从设备中被读到RAM,并被执行。 “主引导记录”只有512个字节,放不了太多东西。它的主要作用是,告诉计算机到硬盘的哪一个位置去找操作系统。
其中,第二部分”分区表”的作用,是将硬盘分成若干个区。 分区表硬盘分区有很多好处。考虑到每个区可以安装不同的操作系统,”主引导记录”因此必须知道将控制权转交给哪个区。分区表的长度只有64个字节,里面又分成四项,每项16个字节。所以,一个硬盘最多只能分四个一级分区,又叫做“主分区”。
最后的四个字节(”主分区的扇区总数”),决定了这个主分区的长度。也就是说,一个主分区的扇区总数最多不超过2的32次方。 如果每个扇区为512个字节,就意味着单个分区最大不超过2TB。再考虑到扇区的逻辑地址也是32位,所以单个硬盘可利用的空间最大也不超过2TB。 如果想使用更大的硬盘,只有2个方法:
引导操作系统的过程由硬盘启动时,BIOS通常是转向第一块硬盘的第一个扇区,即主引导记录(MBR)。 装载记录 基本引导装载程序所做的唯一的事情就是装载第二引导装载程序。 装载Grub 这第二引导装载程序实际上是引出更高级的功能,以允许用户装载一个特定的操作系统。 装载系统 如linux内核。GRUB把机器的控制权移交给操作系统。 不同的是,微软操作系统都是使用一种称为链式装载的引导方法来启动的,主引导记录仅仅是简单地指向操作系统所在分区的第一个扇区。 加载主引导加载程序-基本装载程序众所周知,硬盘上第0磁道第一个扇区被称为MBR,也就是Master Boot Record,即主引导记录,它的大小是512字节,别看地方不大,可里面却存放了预启动信息、分区表信息。 按照BIOS所设定的系统启动流程,如果检测通过,则根据引导次序(Boot Sequence)开始在第一台设备上支持启动程序,我们的启动设备主要包括硬盘、USB、SD等,我们一般用的是硬盘,然后进行读取第一个设备就是硬盘,第一个要读去的就是该硬盘的主引导记录MBR(Master Boot Record),然后系统可以根据启动区安装的引导加载程序(Boot Loader)开始执行核心识别的工作。
然后将控制权交给主引导代码。主引导代码的任务包括
加载次引导记载程序–高级装载程序bootload如GRUB系统读取内存中的grub配置信息(一般为menu.lst或grub.lst),并依照此配置信息来启动不同的操作系统。 这时,计算机的控制权就要转交给硬盘的某个分区了,这里又分成三种情况。
计算机先读取扩展分区的第一个扇区,叫做“扩展引导记录”(Extended boot record,缩写为EBR)。它里面也包含一张64字节的分区表,但是最多只有两项(也就是两个逻辑分区)。 计算机接着读取第二个逻辑分区的第一个扇区,再从里面的分区表中找到第三个逻辑分区的位置,以此类推,直到某个逻辑分区的分区表只包含它自身为止(即只有一个分区项)。因此,扩展分区可以包含无数个逻辑分区。 但是,似乎很少通过这种方式启动操作系统。如果操作系统确实安装在扩展分区,一般采用下一种方式启动。
在这种情况下,计算机读取”主引导记录”前面446字节的机器码之后,不再把控制权转交给某一个分区,而是运行事先安装的“启动管理器”(boot loader),由用户选择启动哪一个操作系统。 Linux环境中,目前最流行的启动管理器是Grub。 Boot Loader 就是在操作系统内核运行之前运行的一段小程序。通过这段小程序,我们可以初始化硬件设备、建立内存空间的映射图,从而将系统的软硬件环境带到一个合适的状态,以便为最终调用操作系统内核做好一切准备。 Boot Loader有若干种,其中Grub、Lilo和spfdisk是常见的Loader。 我们以Grub为例来讲解吧,毕竟用lilo和spfdisk的人并不多。 为什么这么复杂早期的操作系统并没有那么复杂,当然bootload也没有那么多功能,但是如今我们的操作系统越来越复杂,bootload也越来越庞大,而且如今在一台电脑上安装多系统变得那么平常,因此之前简单的bootload已经无法满足这些功能。 BIOS和MBR都是硬件本身会支持的功能,至于Boot Loader则是操作系统安装在MBR上面的一套软件。由于MBR仅有446bytes而已,因此这个引导加载程序是非常小而完美的。这个BootLoader的主要任务如下
上面的前两点还容易理解,但是第三点很有趣!那表示你的计算机系统里面可以具有两个以上的引导加载程序呢。有可能吗?我们的硬盘不是只有一个MBR而已?但是引导加载程序除了可以安装在MBR之外,还可以安装在每个分区的引导扇区。 举一个例子来说,假设你的个人计算机只有一块硬盘,里面分成4个分区。其中第一,二分区分别安装了Windows及Linux,你要如何在开机的时候选择用Windows还是Linux开机呢?假设MBR内安装的是可以同时识别Windows和Linux操作系统的引导加载程序,那么整个流程如下 做个总结就是这样:
加载操作系统内核用户选择要加载的内核之后,次引导加载程序(GRUB)就会根据/boot/grub.conf配置文件中所设置的信息,从/boot/所在的分区上读取Linux内核映像,然后把内核映像加载到内存中并把控制权交给Linux内核。 linux内核获得控制权之后开始干自己的事
根据grub设定的内核映像所在路径,系统读取内存映像,并进行解压缩操作。此时,屏幕一般会输出 启动第五步--用户层init依据inittab文件来设定运行等级 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你如果打开了此文件,里面有一句话,读过之后,你就会对此命令的作用一目了然: # This script will be executed *after* all the other init scripts.# 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程序,进入登录状态 |
|