启动顺序:
BIOS -> MBR(stage1) -> stage2(/boot) -> /etc/grub.conf -> kernel -> /root -> /sbin/init -> /etc/inittab -> /etc/rc.d/rc.sysinit -> /etc/rc.d/rc -> /etc/rc.d/rc?.d/ -> /etc/rc.d/rc.local
1. BIOS自检
Basic Input Output System 基本输入输出系统
它是一组固化到计算机内主板上一个ROM芯片上的程序,它保存着计算机最重要的基本输入输出的程序、开机后自检程序和系统自启动程序
其主要功能是为计算机提供最底层的、最直接的硬件设置和控制
早期的BIOS芯片确实是”只读”的,一旦写入就不能更改,除非更换芯片
2. BIOS两个阶段
POST和Runtime服务。POST阶段完成后它将从存储器中被清除,而Runtime服务会被一直保留,用于目标操作系统的启动
- 上电自检POST(Power-on self test),主要负责检测系统外围关键设备(如:CPU、内存、显卡、I/O、键盘鼠标等)是否正常。例如,最常见的是内存松动的情况,BIOS自检阶段会报错,系统就无法启动起来
- 根据BIOS中设置的系统启动顺序搜索用于启动系统的驱动器,如硬盘、光盘、U盘、软盘和网络。我们以硬盘启动为例,BIOS此时去读取硬盘驱动器的第一个扇区(MBR,512字节),然后执行里面的代码。实际上这里BIOS并不关心启动设备第一个扇区中是什么内容,它只是负责读取该扇区内容、并执行
至此,BIOS的任务就完成了,此后将系统启动的控制权移交到MBR部分的代码
3. 加载MBR
Master Boot Record 主引导记录
驱动器最前端的一段引导扇区
硬盘的0柱面、0磁头、1扇区称为主引导扇区(也叫主引导记录MBR)。它由三个部分组成:
- 主引导程序:在总共512字节的主引导扇区里主引导程序(boot loader)占446个字节
- 硬盘分区表DPT(Disk Partition table):即DPT,占64个字节,硬盘中分区有多少以及每一分区的大小都记在其中
-
分区有效标志:magic number(“魔数”),占2个字节,固定为0xAA55或0x55AA,这取决于处理器类型,如果是小端模式处理器(如Intel系列),则该值为0xAA55;如果是大端模式处理器(如Motorola6800),则该值为0x55AA。(判定是不是分区表)
4. 磁盘分区表
从偏移01BEH开始到偏移01FDH结束的64字节 [447-510]
硬盘分区表可平分为四小部分,每一小部分表示一个分区的信息,占16字节
因此,硬盘的总分区数为什么不能大于4。其中可激活分区数不得大于3,扩展分区数不得大于1,当前活动分区数必须小于等于1
- [0]:Activeflag 活动标志。若为0x80H,则表示该分区为活动分区;若为0x00H,则表示该分区为非活动分区
- [1,2,3]:该分区的起始磁头号,扇区号,柱面号。其中磁头号1字节,扇区号2字节的低6位,柱面号2字节的高2位 + 3字节
- [4]:分区文件系统标志。
分区未用: 0x00H
扩展分区: 0x05H,0x0FH
FAT16分区: 0x06H
FAT32分区: 0x0BH,0x1BH,0x0CH,0x1CH
NTFS分区: 0x07H - [5,6,7]:该分区的结束磁头号,扇区号,柱面号
- [8,9,10,11]:逻辑起始扇区号
- [12,13,14,15]:该分区所占用的扇区数
5. Boot Loader
Boot Loader 是在操作系统内核运行之前运行的一段小程序。可以初始化硬件设备、建立内存空间的映射图
Boot Loader有若干种,常见的有Grub、Lilo和spfdisk
grub是同时支持linux和windows的。但windows的加载程序并不支持linux文件系统,所以在多重启动设置的时候,总是要先装windows而后装Linux
6. GRUB
GNU GRUB(GRand Unified Bootloader)多操作系统启动程序
大多数bootloader都分为stage1和stage2两部分。依赖于CPU体系结构的代码(如设备初始化代码等)通常都放在stage1且可以用汇编语言来实现;而stage2则通常用C语言来实现,这样可以实现复杂的功能,而且有更好的可读性和移植性
- stage1:stage1是直接被写入到MBR中去的,这样机器一启动检测完硬件后,就将控制权交给了GRUB的代码
BIOS将stage1载入内存中0x7c00处并跳转执行
stage1.S这汇编出来的512个字节代码的作用是将0柱面,0磁道,2扇区的512字节copy到0x8000处 - stage2:stage2不在MBR,这是因为由于stage2很大,没有办法存放在MBR中
stage1.S是grub的第一个文件,编译后产生的代码,正好是512字节,不是正好,是必须,否则无法放入1个扇区
# grub
Probing devices to guess BIOS drives. This may take a long time.
GNU GRUB version 0.97 (640K lower / 3072K upper memory)
[ Minimal BASH-like line editing is supported. For the first word, TAB
lists possible command completions. Anywhere else TAB lists the possible
completions of a device/filename.]
grub> root (hd0,0) #指定启动分区
root (hd0,0)
Filesystem type is ext2fs, partition type 0x83
grub> setup (hd0) #将grub安装在主引导记录上
setup (hd0)
Checking if "/boot/grub/stage1" exists... no
Checking if "/grub/stage1" exists... yes
Checking if "/grub/stage2" exists... yes
Checking if "/grub/e2fs_stage1_5" exists... yes
Running "embed /grub/e2fs_stage1_5 (hd0)"... 26 sectors are embedded.
succeeded
Running "install /grub/stage1 (hd0) (hd0)1+26 p (hd0,0)/grub/stage2 /grub/grub.conf"... succeeded
Done.
7. 0x7C00
它不属于Intel x86平台规范的,而是属于BIOS规范中定义的内容
0x7C00 = 32kb - 1024b
他们想留下32kb内更多的空间给操作系统来加载自己
8. MBR和stage1
dd获取MBR
# dd if=/dev/sda of=mbr bs=512 count=1
# hexdump mbr
0000000 48eb 1090 d08e 00bc b8b0 0000 d88e c08e
0000010 befb 7c00 00bf b906 0200 a4f3 21ea 0006
0000020 be00 07be 0438 0b75 c683 8110 fefe 7507
0000030 ebf3 b416 b002 bb01 7c00 80b2 748a 0203
0000040 0080 8000 89d4 0004 0800 90fa f690 80c2
0000050 0275 80b2 59ea 007c 3100 8ec0 8ed8 bcd0
0000060 2000 a0fb 7c40 ff3c 0274 c288 f652 80c2
0000070 5474 41b4 aabb cd55 5a13 7252 8149 55fb
0000080 75aa a043 7c41 c084 0575 e183 7401 6637
0000090 4c8b be10 7c05 44c6 01ff 8b66 441e c77c
00000a0 1004 c700 0244 0001 8966 085c 44c7 0006
00000b0 6670 c031 4489 6604 4489 b40c cd42 7213
00000c0 bb05 7000 7deb 08b4 13cd 0a73 c2f6 0f80
00000d0 f084 e900 008d 05be c67c ff44 6600 c031
00000e0 f088 6640 4489 3104 88d2 c1ca 02e2 e888
00000f0 f488 8940 0844 c031 d088 e8c0 6602 0489
0000100 a166 7c44 3166 66d2 34f7 5488 660a d231
0000110 f766 0474 5488 890b 0c44 443b 7d08 8a3c
0000120 0d54 e2c0 8a06 0a4c c1fe d108 6c8a 5a0c
0000130 748a bb0b 7000 c38e db31 01b8 cd02 7213
0000140 8c2a 8ec3 4806 607c b91e 0100 db8e f631
0000150 ff31 f3fc 1fa5 ff61 4226 be7c 7d7f 40e8
0000160 eb00 be0e 7d84 38e8 eb00 be06 7d8e 30e8
0000170 be00 7d93 2ae8 eb00 47fe 5552 2042 4700
0000180 6f65 006d 6148 6472 4420 7369 006b 6552
0000190 6461 2000 7245 6f72 0072 01bb b400 cd0e
00001a0 ac10 003c f475 00c3 0000 0000 0000 0000
00001b0 0000 0000 0000 0000 81f8 0008 0000 2080
00001c0 0021 5e83 2638 0800 0000 6000 0009 5e00
00001d0 2639 fe83 ffff 6800 0009 9800 01f9 fe00
00001e0 ffff fe82 ffff 0000 0203 0000 007d 0000
00001f0 0000 0000 0000 0000 0000 0000 0000 aa55
0000200
# hexdump /boot/grub/stage1
0000000 48eb 1090 d08e 00bc b8b0 0000 d88e c08e
0000010 befb 7c00 00bf b906 0200 a4f3 21ea 0006
0000020 be00 07be 0438 0b75 c683 8110 fefe 7507
0000030 ebf3 b416 b002 bb01 7c00 80b2 748a 0203
0000040 0080 8000 89d4 0004 0800 90fa f690 80c2
0000050 0275 80b2 59ea 007c 3100 8ec0 8ed8 bcd0
0000060 2000 a0fb 7c40 ff3c 0274 c288 f652 80c2
0000070 5474 41b4 aabb cd55 5a13 7252 8149 55fb
0000080 75aa a043 7c41 c084 0575 e183 7401 6637
0000090 4c8b be10 7c05 44c6 01ff 8b66 441e c77c
00000a0 1004 c700 0244 0001 8966 085c 44c7 0006
00000b0 6670 c031 4489 6604 4489 b40c cd42 7213
00000c0 bb05 7000 7deb 08b4 13cd 0a73 c2f6 0f80
00000d0 f084 e900 008d 05be c67c ff44 6600 c031
00000e0 f088 6640 4489 3104 88d2 c1ca 02e2 e888
00000f0 f488 8940 0844 c031 d088 e8c0 6602 0489
0000100 a166 7c44 3166 66d2 34f7 5488 660a d231
0000110 f766 0474 5488 890b 0c44 443b 7d08 8a3c
0000120 0d54 e2c0 8a06 0a4c c1fe d108 6c8a 5a0c
0000130 748a bb0b 7000 c38e db31 01b8 cd02 7213
0000140 8c2a 8ec3 4806 607c b91e 0100 db8e f631
0000150 ff31 f3fc 1fa5 ff61 4226 be7c 7d7f 40e8
0000160 eb00 be0e 7d84 38e8 eb00 be06 7d8e 30e8
0000170 be00 7d93 2ae8 eb00 47fe 5552 2042 4700
0000180 6f65 006d 6148 6472 4420 7369 006b 6552
0000190 6461 2000 7245 6f72 0072 01bb b400 cd0e
00001a0 ac10 003c f475 00c3 0000 0000 0000 0000
00001b0 0000 0000 0000 0000 0000 0000 0000 1224
00001c0 090f be00 7dbd c031 13cd 8a46 800c 00f9
00001d0 0f75 dabe e87d ffc9 97eb 6c46 706f 7970
00001e0 bb00 7000 01b8 b502 b600 cd00 7213 b6d7
00001f0 b501 e94f fee0 0000 0000 0000 0000 aa55
0000200
不一样的地方是[0x1b8, 0x1bb)
Windows系的产品会用到这4个字节,对于Linux和grub是用不到这4个字节的
9. 加载内核
当stage2被载入内存执行时,它首先会去解析grub的配置文件/boot/grub/grub.conf。然后加载内核镜像到内存中,并将控制权转交给内核。而内核会立即初始化系统中各设备并做相关的配置工作,其中包括CPU、I/O、存储设备等
关于Linux的设备驱动程序的加载,有一部分驱动程序直接被编译进内核镜像中,另一部分驱动程序则是以模块的形式放在initrd(ramdisk)中
实际上Linux的内核镜像仅是包含了基本的硬件驱动,在系统安装过程中会检测系统硬件信息,根据安装信息和系统硬件信息将一部分设备驱动写入 initrd
当所需的驱动程序加载完后,会创建一个根设备,然后将根文件系统rootfs以只读的方式挂载
10. initramfs
/boot/initramfs-2.6.32-71.el6.x86_64.img
当内核启动时,内核将这个 cpio包解开,并且将其中包含的文件系统释放到rootfs中
11. /sbin/init
转到真正的根文件系统上面去,同时运行/sbin/init程序,执行系统的1号进程。此后系统的控制权交给/sbin/init进程
- 读取/etc/inittab。设置init初始化程序初始化脚本
- 执行系统初始化脚本 /etc/rc.d/rc.sysinit。激活交换分区,检查磁盘,加载硬件模块以及其它一些需要优先执行任务
- 执行/etc/rc.d/rc脚本。服务启动的顺序是先K后S,字母后数字越小的脚本越先执行
12. /etc/inittab
id:runlevels:action:process
# cat /etc/inittab
id:5:initdefault: //运行级别5
action是描述其后的process的运行方式的,action可取的值包括:initdefault、sysinit、boot、bootwait等
initdefault是一个特殊的action值,用于标识缺省的启动级别;当init由核心激活以后,它将读取inittab中的initdefault项,取得其中的runlevel,并作为当前的运行级别。如果没有inittab文件,或者其中没有initdefault项,init将在控制台上请求输入runlevel
sysinit、boot、bootwait等action将在系统启动时无条件运行,而忽略其中的runlevel
13. 启动流程图
参考文献:
http://blog.chinaunix.net/uid-23069658-id-3142047.html
http://blog.chinaunix.net/uid-24774106-id-3497929.html
http://roclinux.cn/?p=1301
http://blog.itpub.net/8111049/viewspace-680043
http://www.douban.com/note/249471773/