在日常生活中,我们开机的操作一般为按下电源键,等待系统自己起来就好了。这开机的过程看似简单,但其中却包含着十分复杂的各种小过程。以Linux为例,其流程为下图所示:
一、POST
首先,先介绍下BIOS和POST的概念。
BIOS:Basic Input Output System,即基本输入输出系统,它是一组固化到计算机内主板上一个ROM芯片上的程序,它保存着计算机最重要的基本输入输出的程序、开机后自检程序和系统自启动程序,它可从CMOS中读写系统设置的具体信息。其主要功能是为计算机提供最底层的、最直接的硬件设置和控制。
POST:Power on self test,即加电自检,它是BIOS功能的一个部分,责完成对CPU、主板、内存、软硬盘子系统、显示子系统(包括显示缓存)、串并行接口、键盘、CD-ROM光驱等的检测。主要检查硬件的好坏。
当我们按下电源键时,BIOS就会先启动POST功能,检查自身硬件的状态并反馈,如果硬件有问题则会导致系统启动失败。如果硬件正常,则进入下一步。
二、BootSequence
bootsequence为启动顺序,可在BIOS中设置。如下图:
BIOS会根据次序查找各引导设备,其查找到的第一个有引导程序(bootloader)的设备即为本次启动要用到的设备。
以硬盘启动为例,BIOS此时去读取硬盘驱动器的第一个扇区(MBR,512字节),然后执行里面的代码。实际上这里BIOS并不关心启动设备第一个扇区中是什么内容,它只是负责读取该扇区内容、并执行。
至此,BIOS的任务就完成了,此后将系统启动的控制权移交到MBR部分的代码。
三、Bootloader(MBR)
MBR:Master Boot Record,即主引导记录,是硬盘驱动器上的第一个扇区,它的大小为512Bytes,由三个部分组成。分别为主引导程序(Bootloader)、硬盘分区表DPT(Disk Partition table)和硬盘有效标志(55AA),其大小分别为446Bytes,64Bytes和2Bytes。
BootLoader是在操作系统内核运行之前运行的程序。它可以初始化硬件设备、建立内存空间映射图,从而将系统的软硬件环境带到一个合适状态,以便为最终调用操作系统内核准备好正确的环境。
在Linux中,常用的bootloader有grub和lilo,我们以grub为例:
grub:Grand Uniform Bootloader,它是一个多重操作系统管理器,可以引导不同的操作系统。一般来说,它的引导有2个阶段stage1和stage2:
stage1:stage1的代码是存放在MBR中的前446Bytes中的,也就是说,BIOS会先把它加载到内存中执行。stage1没有识别文件系统的能力,它仅仅是是stage2的入口。
stage1_5:stage1_5是MBR之后的扇区,它可以让stage1中的bootloader识别stage2所在的分区上的文件系统,是stage1和stage2之间的桥梁。
stage2:现在可以访问/boot/grub/中的stage2文件,并将其装入内存中执行。它的作用为:
(1)提供菜单、并提供交互式接口
e:编辑模式,用于编辑菜单
c:命令模式,交互式接口
(2)加载用户选择的内核或操作系统
允许传递参数给内核
可隐藏此菜单
(3)为菜单提供了保护机制
为编辑菜单提供认证
为启用内核或操作系统提供认证
四、Kernel
当stage2被装入内存中执行后,它会去解析/boot/grub/grub.conf文件,并根据该配置文件来加载Kernel(内核)镜像和initrd至内存。此时,内核将得到系统控制权并立即初始化系统中各设备并做相关的配置工作,其中包括CPU、I/O、存储设备等。
initrd:bootloader initialized RAM disk,即为bootloader初始化的内存盘。因为内核在初始化系统各硬件设备时需要加载不同的驱动程序,而每个系统的硬件架构并不是相同的,内核编译了一部分硬件驱动,而另一部分则被放置在initrd中。
实际上Linux的内核镜像仅是包含了基本的硬件驱动,在系统安装过程中会检测系统硬件信息,根据安装信息和系统硬件信息将一部分设备驱动写入initrd。这样在以后启动系统时,一部分设备驱动就放在initrd中来加载。
注:initramfs是initrd的升级优化。
内核在获得控制权初始化后,会去执行initrd中的init脚本,这时内核将控制权交给了init文件处理。当所需的驱动程序加载完后,会创建一个根设备,然后将根文件系统rootfs以只读的方式挂载。这一步结束后,释放未使用的内存,并通过switchroot转换到真正的根文件系统上面去,同时运行/sbin/init程序。此后系统的控制权就全权交给/sbin/init进程了。
五、/sbin/init
1、运行级别:
/sbin/init进程是用来初始化系统的进程,它是所有进程的父进程。当/sbin/init进程获得了系统的控制权之后,它会先读取/etc/inittab文件来确定系统的运行级别。
CentOS6.7的/etc/inittab文件:
[[email protected] initrd]# vim /etc/inittab
# inittab is only used by upstart for the default runlevel.
#
# ADDING OTHER CONFIGURATION HERE WILL HAVE NO EFFECT ON YOUR SYSTEM.
#
# System initialization is started by /etc/init/rcS.conf
#
# Individual runlevels are started by /etc/init/rc.conf
#
# Ctrl-Alt-Delete is handled by /etc/init/control-alt-delete.conf
#
# Terminal gettys are handled by /etc/init/tty.conf and /etc/init/serial.conf,
# with configuration in /etc/sysconfig/init.
#
# For information on how to write upstart event handlers, or how
# upstart works, see init(5), init(8), and initctl(8).
#
# Default runlevel. The runlevels used are:
# 0 - halt (Do NOT set initdefault to this)
# 1 - Single user mode
# 2 - Multiuser, without NFS (The same as 3, if you do not have networking)
# 3 - Full multiuser mode
# 4 - unused
# 5 - X11
# 6 - reboot (Do NOT set initdefault to this)
#
id:3:initdefault:
~
~
~
~
运行级别是为了系统的运行或维护等目的而设定的机制,一共有7个级别,分别用数字0-6表示:
0:关机,shutdown
1:单用户模式(single user),root用户,无需认证;维护模式
2:多用户模式(multi user),会启动网络功能,但不会启动NFS;维护模式
3:多用户模式(multi user),完全功能模式;文本界面,无图形界面
4:预留级别:目前无特别使用目的,但习惯以同3级别功能使用
5:多用户模式(multi user),完全功能模式,图形界面
6:重启,reboot
默认级别一般为3或5。
2、系统初始化
确定运行级别后,/sbin/init程序会读取/etc/rc.d/rc.sysinit这个系统初始化脚本进行系统初始化操作,包括以下部分:
a、读取/etc/sysconfig/network/文件来设置主机名
b、设置欢迎信息
c、激活udev和selinux
d、挂载/etc/fstab文件中定义的所有文件系统
e、检测根文件系统,并以读写方式重新挂载根文件系统
f、设置系统时钟
g、根据/etc/sysctl.conf文件来设置内核参数
h、激活lvm及软raid
i、激活swap设备
j、加载额外设备的驱动程序
k、清理操作
3、服务的启停
系统初始化之后,系统就可以使用了,但是往往还需要启动一些相应的服务来使用网络或主机功能。此时/sbin/init程序会读取/etc/rc.d/rc文件并根据运行级别来判断停止某些服务并启动某些服务。S
需要启停的服务脚本都存放于/etc/rc$runlevel.d/目录下,其中K开头的脚本为要关闭的服务脚本,K后面的数字越小,优先级越高,需先关闭。而S开头的脚本为要开启的服务脚本,S后面的数字越小,优先级越高,需先启动。实际上,所有/etc/rc$runlevel.d/目录下的脚本均为/etc/init.d/目录下的脚本链接。
4、启动终端
在启动所有需要的服务后,系统会启动终端或图形终端来等待用户登录。至此,整个系统启动流程就结束了。
5、执行用户自定义引导程序/etc/rc.d/rc.local。其实当执行/etc/rc.d/rc3.d/S99local时,它就是在执行/etc/rc.d/rc.local。S99local是指向rc.local的符号链接。就是一般来说,自定义的程序不需要执行上面所说的繁琐的建立shell增加链接文件的步骤,只需要将命令放在rc.local里面就可以了,这个shell脚本就是保留给用户自定义启动内容的。
六、总结
简要流程:
POST-->BootSequence(启动顺序)-->BootLoader(MBR,grub)-->Kennel(initrd)-->rootfs(readonly)-->switchroot-->/sbin/init-->设置默认运行级别-->运行系统初始化脚本,完成系统初始化-->关闭对应级别下需要停止的服务,启动对应级别下需要开启的服务-->设置登录终端[-->启动图形终端]
http://blog.chinaunix.net/uid-23069658-id-3142047.html