linux内核启动流程[转]

启动流程一览

既然启动是很严肃的一件事,那咱们就来了解一下整个启动的过程吧! 好让你们比较容易发现启动过程里面可能会发生问题的地方,以及出现问题后的解决之道! 不过,由於启动的过程当中,那个启动管理程序 (Boot Loader) 使用的软件可能不同,例如目前各大 Linux distributions 的主流为 grub,但早期 Linux 默认是使用 LILO 。 但不管如何,咱们老是得要了解整个 boot loader 的工做状况,才能了解为什么进行多重启动的配置时, 总是听人家讲要先安装 Windows 再安装 Linux 的缘由~php

假设以我的计算机架设的 Linux 主机为例 , 当你按下电源按键后计算机硬件会主动的读取 BIOS 来加载硬件资讯及进行硬件系统的自我测试, 以后系统会主动的去读取第一个可启动的装置 (由 BIOS 配置的) ,此时就能够读入启动管理程序了。node

启动管理程序能够指定使用哪一个核心文件来启动,并实际加载核心到内存当中解压缩与运行, 此时核心就可以开始在内存内活动,并侦测全部硬件资讯与加载适当的驱动程序来使整部主机开始运行, 等到核心侦测硬件与加载驱动程序完毕后,一个最阳春的操做系统就开始在你的 PC 上面跑了。linux

主机系统开始运行后,此时 Linux 才会呼叫外部程序开始准备软件运行的环境, 而且实际的加载全部系统运行所须要的软件程序哩!最后系统就会开始等待你的登录与操做啦! 简单来讲,系统启动的通过能够汇整成底下的流程的:shell

  1. 加载 BIOS 的硬件资讯与进行自我测试,并依据配置取得第一个可启动的装置;
  2. 读取并运行第一个启动装置内 MBR 的 boot Loader (亦便是 grub, spfdisk 等程序);
  3. 依据 boot loader 的配置加载 Kernel ,Kernel 会开始侦测硬件与加载驱动程序;

BIOS, 启动自我测试与 MBR

在我的计算机架构下,你想要启动整部系统首先就得要让系统去加载 BIOS (Basic Input Output System),并透过 BIOS 程序去加载 CMOS 的资讯,而且藉由 CMOS 内的配置值取得主机的各项硬件配置, 例如 CPU 与周边设备的沟通时脉啊、启动装置的搜寻顺序啊、硬盘的大小与类型啊、 系统时间啊、各周边汇流排的是否启动 Plug and Play (PnP, 随插即用装置) 啊、 各周边设备的 I/O 位址啊、以及与 CPU 沟通的 IRQ 岔断等等的资讯。windows

在取得这些资讯后,BIOS 还会进行启动自我测试 (Power-on Self Test, POST) 。 而后开始运行硬件侦测的初始化,并配置 PnP 装置,以后再定义出可启动的装置顺序, 接下来就会开始进行启动装置的数据读取了 (MBR 相关的任务开始)。bash

由於咱们的系统软件大多放置到硬盘中嘛!因此 BIOS 会指定启动的装置好让咱们能够读取磁碟中的操做系统核心文件。 但由於不一样的操做系统他的文件系统格式不相同,所以咱们必需要以一个启动管理程序来处理核心文件加载 (load) 的问题, 所以这个启动管理程序就被称为 Boot Loader 了。那这个 Boot Loader 程序安装在哪里呢?就在启动装置的第一个磁区 (sector) 内,也就是咱们一直谈到的 MBR (Master Boot Record, 主要启动记录区)。网络

那你会不会以为很奇怪啊?既然核心文件须要 loader 来读取,那每一个操做系统的 loader 都不相同, 这样的话 BIOS 又是如何读取 MBR 内的 loader 呢?颇有趣的问题吧!其实 BIOS 是透过硬件的 INT 13 中断功能来读取 MBR 的,也就是说,只要 BIOS 可以侦测的到你的磁碟 (不论该磁碟是 SATA 仍是 IDE 介面),那他就有办法透过 INT 13 这条通道来读取该磁碟的第一个磁区内的 MBR 啦!这样 boot loader 也就可以被运行罗!架构

咱们知道每颗硬盘的第一个磁区内含有 446 bytes的 MBR 区域,那么若是个人主机上面有两颗硬盘的话, 系统会去哪颗硬盘的 MBR 读取 boot loader 呢?这个就得要看 BIOS 的配置了。 基本上,咱们经常讲的『系统的 MBR』其实指的是 第一个启动装置的 MBR 才对! 因此,改天若是你要将启动管理程序安装到某颗硬盘的 MBR 时, 要特别注意当时系统的『第一个启动装置』是哪一个,不然会安装到错误的硬盘上面的 MBR 喔! 测试

 

Boot Loader

刚刚说到 Loader 的最主要功能是要认识操做系统的文件格式并据以加载核心到主内存中去运行。 由於不一样操做系统的文件格式不一致,所以每种操做系统都有本身的 boot loader 啦!用本身的 loader 才有办法加载核心文件嘛!那问题就来啦,你应该有据说过多重操做系统吧?也就是在一部主机上面安装多种不一样的操做系统。 既然你 (1)必需要使用本身的 loader 才可以加载属於本身的操做系统核心,而 (2)系统的 MBR 只有一个,那你怎么会有办法同时在一部主机上面安装 Windows 与 Linux 呢?spa

其实每一个文件系统 (filesystem, 或者是 partition) 都会保留一块启动磁区 (boot sector) 提供操做系统安装 boot loader , 而一般操做系统默认都会安装一份 loader 到他根目录所在的文件系统的 boot sector 上。若是咱们在一部主机上面安装 Windows 与 Linux 后,该 boot sector, boot loader 与 MBR 的相关性会有点像下图:


图 1.2.一、 boot loader 安装在 MBR, boot sector 与操做系统的关系

如上图所示,每一个操做系统默认是会安装一套 boot loader 到他本身的文件系统中 (就是每一个 filesystem 左下角的方框),而在 Linux 系统安装时,你能够选择将 boot loader 安装到 MBR 去,也能够选择不安装。 若是选择安装到 MBR 的话,那理论上你在 MBR 与 boot sector 都会保有一份 boot loader 程序的。 至於 Windows 安装时,他默认会主动的将 MBR 与 boot sector 都装上一份 boot loader!因此啦, 你会发现安装多重操做系统时,你的 MBR 经常会被不一样的操做系统的 boot loader 所覆盖啦! ^_^

咱们刚刚提到的两个问题仍是没有解决啊!虽然各个操做系统均可以安装一份 boot loader 到他们的 boot sector 中, 这样操做系统能够透过本身的 boot loader 来加载核心了。问题是系统的 MBR 只有一个哩! 你要怎么运行 boot sector 里面的 loader 啊?

boot loader 主要的功能以下:

  • 提供菜单:使用者能够选择不一样的启动项目,这也是多重启动的重要功能!
  • 加载核心文件:直接指向可启动的程序区段来开始操做系统;
  • 转交其余 loader:将启动管理功能转交给其余 loader 负责。

由於具备菜单功能,所以咱们能够选择不一样的核心来启动。而由於具备控制权转交的功能,所以咱们能够加载其余 boot sector 内的 loader 啦!不过 Windows 的 loader 默认不具备控制权转交的功能,所以你不能使用 Windows 的 loader 来加载 Linux 的 loader 喔!这也是为啥第三章谈到 MBR 与多重启动时,会特别强调先装 Windows 再装 Linux 的缘故。 咱们将上述的三个功能以底下的图示来解释你就看的懂了!(与第三章的图示也很是相似啦!)


图 1.2.二、 启动管理程序的菜单功能与控制权转交功能示意图

如上图所示,个人 MBR 使用 Linux 的 grub 这个启动管理程序,而且里面假设已经有了三个菜单, 第一个菜单能够直接指向 Linux 的核心文件而且直接加载核心来启动;第二个菜单能够将启动管理程序控制权交给 Windows 来管理,此时 Windows 的 loader 会接管启动流程,这个时候他就可以启动 windows 了。第三个菜单则是使用 Linux 在 boot sector 内的启动管理程序,此时就会跳出另外一个 grub 的菜单啦!了解了吗?

而最终 boot loader 的功能就是『加载 kernel 文件』啦!

 

加载核心侦测硬件与 initrd

当咱们藉由 boot loader 的管理而开始读取核心文件后,接下来, Linux 就会将核心解压缩到主内存当中, 而且利用核心的功能,开始测试与驱动各个周边装置,包括储存装置、CPU、网络卡、声卡等等。 此时 Linux 核心会以本身的功能从新侦测一次硬件,而不必定会使用 BIOS 侦测到的硬件资讯喔!也就是说,核心此时才开始接管 BIOS 后的工做了。 那么核心文件在哪里啊?通常来讲,他会被放置到 /boot 里面,而且取名为 /boot/vmlinuz 才对!

[root@www ~]# ls --format=single-column -F /boot
config-2.6.18-92.el5      <==此版本核心被编译时选择的功能与模块配置档
grub/                     <==就是启动管理程序 grub 相关数据目录
initrd-2.6.18-92.el5.img  <==虚拟文件系统档!
System.map-2.6.18-92.el5  <==核心功能放置到内存位址的对应表
vmlinuz-2.6.18-92.el5     <==就是核心文件啦!最重要者!

从上表咱们也能够知道此版本的 Linux 核心为 2.6.18-92.el5 这个版本!为了硬件开发商与其余核心功能开发者的便利, 所以 Linux 核心是能够透过动态加载核心模块的 (就请想成驱动程序便可),这些核心模块就放置在 /lib/modules/ 目录内。 因为模块放置到磁盘根目录内 (要记得 /lib 不能够与 / 分别放在不一样的 partition !), 所以在启动的过程当中核心必需要挂载根目录,这样才可以读取核心模块提供加载驱动程序的功能。 并且为了担忧影响到磁碟内的文件系统,所以启动过程当中根目录是以惟读的方式来挂载的喔。

通常来讲,非必要的功能且能够编译成为模块的核心功能,目前的 Linux distributions 都会将他编译成为模块。 所以 U盘, SATA, SCSI... 等磁碟装置的驱动程序一般都是以模块的方式来存在的。 如今来思考一种状况,假设你的 linux 是安装在 SATA 磁碟上面的,你能够透过 BIOS 的 INT 13 取得 boot loader 与 kernel 文件来启动,而后 kernel 会开始接管系统而且侦测硬件及尝试挂载根目录来取得额外的驱动程序。

 

问题是,核心根本不认识 SATA 磁碟,因此须要加载 SATA 磁碟的驱动程序, 不然根本就没法挂载根目录。可是 SATA 的驱动程序在 /lib/modules 内,你根本没法挂载根目录又怎么读取到 /lib/modules/ 内的驱动程序?是吧!很是的两难吧!在这个状况之下,你的 Linux 是没法顺利启动的! 那怎办?不要紧,咱们能够透过虚拟文件系统来处理这个问题。

虚拟文件系统 (Initial RAM Disk) 通常使用的档名为 /boot/initrd ,这个文件的特点是,他也可以透过 boot loader 来加载到内存中, 而后这个文件会被解压缩而且在内存当中模拟成一个根目录, 且此模拟在内存当中的文件系统可以提供一支可运行的程序,透过该程序来加载启动过程当中所最须要的核心模块, 一般这些模块就是 U盘, RAID, LVM, SCSI 等文件系统与磁碟介面的驱动程序啦!等加载完成后, 会帮助核心从新呼叫 /sbin/init 来开始后续的正常启动流程。

如上图所示,boot loader 能够加载 kernel 与 initrd ,而后在内存中让 initrd 解压缩成为根目录, kernel 就可以藉此加载适当的驱动程序,最终释放虚拟文件系统,并挂载实际的根目录文件系统, 就可以开始后续的正常启动流程。更详细的 initrd 说明,你能够自行使用 man initrd 去查阅看看。 底下让咱们来了解一下 CentOS 5.x 的 initrd 文件内容有什么吧!

复制代码
# 1. 先将 /boot/initrd 复制到 /tmp/initrd 目录中,等待解压缩:
[root@www ~]# mkdir /tmp/initrd
[root@www ~]# cp /boot/initrd-2.6.18-92.el5.img /tmp/initrd/
[root@www ~]# cd /tmp/initrd
[root@www initrd]# file initrd-2.6.18-92.el5.img
initrd-2.6.18-92.el5.img: gzip compressed data, ...
# 原来是 gzip 的压缩档!由于是 gzip ,因此扩展名给他改为 .gz 吧!

# 2. 将上述的文件解压缩:
[root@www initrd]# mv initrd-2.6.18-92.el5.img initrd-2.6.18-92.el5.gz
[root@www initrd]# gzip -d initrd-2.6.18-92.el5.gz
[root@www initrd]# file initrd-2.6.18-92.el5
initrd-2.6.18-92.el5: ASCII cpio archive (SVR4 with no CRC)
# 搞了老半天,原来仍是 cpio 的命令压缩成的文件啊!解压缩看看!

# 3. 用 cpio 解压缩
[root@www initrd]# cpio -ivcdu < initrd-2.6.18-92.el5
[root@www initrd]# ll
drwx------ 2 root root    4096 Apr 10 02:05 bin
drwx------ 3 root root    4096 Apr 10 02:05 dev
drwx------ 2 root root    4096 Apr 10 02:05 etc
-rwx------ 1 root root    1888 Apr 10 02:05 init
-rw------- 1 root root 5408768 Apr 10 02:00 initrd-2.6.18-92.el5
drwx------ 3 root root    4096 Apr 10 02:05 lib
drwx------ 2 root root    4096 Apr 10 02:05 proc
lrwxrwxrwx 1 root root       3 Apr 10 02:05 sbin -> bin
drwx------ 2 root root    4096 Apr 10 02:05 sys
drwx------ 2 root root    4096 Apr 10 02:05 sysroot
# 看!是否很像根目录!尤为也是有 init 这个运行档!务必看一下权限!
# 接下来看看 init 这个文件内有啥咚咚?

# 4. 观察 init 文件内较重要的运行项目
[root@www initrd]# cat init
#!/bin/nash                  <==使用相似 bash 的 shell 来运行
mount -t proc /proc /proc    <==挂载内存的虚拟文件系统
....(中间省略)....
echo Creating initial device nodes
mknod /dev/null c 1 3        <==建立系统所须要的各项装置!
....(中间省略)....
echo "Loading ehci-hcd.ko module"
insmod /lib/ehci-hcd.ko      <==加载各项核心模块,就是驱动程序!
....(中间省略)....
echo Creating root device.
mkrootdev -t ext3 -o defaults,ro hdc2 <==尝试挂载根目录啦!
....(底下省略)....
复制代码

透过上述运行档的内容,咱们能够知道 initrd 有加载模块而且尝试挂载了虚拟文件系统。 接下来就可以顺利的运行啦!那么是否必定须要 initrd 呢?

是否没有 initrd 就没法顺利启动?
答:
不见得的!须要 initrd 最重要的缘由是,当启动时没法挂载根目录的状况下, 此时就必定须要 initrd ,例如你的根目录在特殊的磁碟介面 (U盘, SATA, SCSI) , 或者是你的文件系统较为特殊 (LVM, RAID) 等等,才会须要 initrd。

若是你的 Linux 是安装在 IDE 介面的磁碟上,而且使用默认的 ext2/ext3 文件系统, 那么不须要 initrd 也可以顺利的启动进入 Linux 的!

在核心完整的加载后,您的主机应该就开始正确的运行了

 

 转自 http://vbird.dic.ksu.edu.tw/linux_basic/0510osloader_1.php

相关文章
相关标签/搜索