CentOS 系统启动流程
前言
Linux 系统的启动及初始化是 Linux 学习过程中非常重要的一个点,只有洞悉系统启动过程、初始化了哪些内容,才能对 Linux 有更加深入的了解。本文主要描述 CentOS 系统( PC 架构)从电脑开机到初始化完成整个过程,包括 cpu 加电自检、 bios 寻找启动项、 bootloader 加载系统内核、系统启动并初始化等等。
总览
POST
--> Boot Sequence
--> Boot Loader
--> Kernel
--> rootfs
--> switchroot
--> /sbin/init
--> ( /etc/inittab , /etc/init/*.conf )
--> 设定默认运行级别
--> 系统初始化脚本
--> 关闭或启动对应级别下的服务
--> 启动终端
第一步:加电自检( POST
)
系统加电之后,首先进行的硬件自检,一但通电后主板会自动读取主板 ROM (只读)中的程序,进行加载,计算机会首先加载 BIOS 系统。然后通过加载 CMOS 检查各种硬件设备是否完整存在,如内存,硬盘,显示, IO 设备等。这个时候机器不能获取外部的存储或者网络信息,一些重要的值(日期、时间、其他外部值)都是从CMOS里读取。如果有硬件故障的话将按两种情况理:对于严重故障(致命性故障)则停机,此时由于各种初始化操作还没完成,不能给出任何提示或信号;对于非严重故障则给出提示或声音报警信号,等待用户处理。如果没有故障, POST 完成自己的接力任务,将尾部工作交接给 BIOS 处理。
第二步:系统启动引导( Boot Sequence
)
BIOS 会按次序查找各引导设备,第一个有引导程序的设备即为本次启动要用到的设备(也可以人工介入进行选择)。决定启动介质按照 BIOS 所设定的系统启动流程,根据引导次序( Boot Sequence )自上而下的寻找对应存储设备上操作系统的 MBR 。
MBR 是启动硬盘上第 0 磁道第一个扇区,也就是 Master Boot Record ,即主引导记录,它的大小仅有 512 bytes ,但里面却存放了引导区、分区表等信息。可分为三部分:
446 bytes
:引导区( bootloader )64 bytes
:分区表( PARTITION TABLE )2 bytes
:55AA(分区有效性标记, 55AA 为有效,其他为无效)
POST 过程结束后,系统的控制权从 BISO 转交到 bootloader 。 Bootloader 一般存储在系统的硬盘上(传统的 BIOS/MBR 系统)。
第三步:启动加载器( Boot Loader
)
Bootloader 的功能:
- 提供一个菜单,允许用户选择要启动的系统或不同的内核版本;
- 把用户选定的内核装载到 RAM 的特定空间中,解压、展开,而后把系统控制权移交给内核;
各个系统的 bootloader 加载器程序也不同:
- Windows:ntloader
- Linux:
- LILO:LIinux LOader(无法支持大磁盘,1024 柱面后的内容不能加载,现一般用于移动设备)
- GRUB:Grand Uniform Bootloader
- GRUB 0.X:Grub Legacy(CentOS 5/6)
- GRUB 1.X:Grub2(CentOS 7)
- Grub 0.X 和 Grub 1.X 是两种几乎完全不一样的版本。
- bootloader(放于 MBR); 1.5. :存放在 MBR 之后的扇区,让第一段中的 bootloader 能识别第二段所在的分区上的文件系统;
- 存放于 /boot/grub (主要负责调用内核及实现其他功能);
图片摘自:http://linux.it.net.cn/CentOS/fast/2016/0103/19557.html注意:除了 MBR 架构,还有 UEFI 、 GPT 等架构,此次主要说 MBR 。
第四步:加载内核( Booting The Kernel
)
Bootloader 加载到内核后,内核会在 ramdisk 中装载(详见《Linux 内核简介》),并进行自身初始化。 初始化流程为:
- 探测可识别到的所有硬件设备;
- 加载硬件驱动程序;(有可能会借助于 ramdisk 加载驱动);
- 以只读方式挂载根文件系统;(确保启动没问题后,再改为读写);
- 运行用户空间的第一个应用程序
/sbin/init
进行系统初始化;
/sbin/init
程序,即开始运行用户空间的第一个程序。 至此,内核级别的启动流程就完成了, /sbin/init
会接手接下来的系统启动流程。
第五步:系统初始化( /sbin/init
)
简介
init
程序的类型分为三种, SysV init
, Upstart
和 Systemd
。 CentOS 5
及之前的系统用的是 SysV init
,而 CentOS 6
用的是 Upstart
,现在 CentOS 7
用的为 Systemd
。
运行级别
init
为了系统的运行或维护等目的,设定了 7 个运行级别:
0
:关机, shutdown ;1
:单用户模式( single user ), root 用户登录,无须认证,属于维护模式;2
:多用户模式( multi user ),会启动网络功能,但不会启动 NFS ,属于维护模式;3
:多用户模式( mutli user ),完全功能模式,文本界面;4
:预留级别:目前无特别使用目的,但习惯以同 3 级别功能使用;5
:多用户模式( multi user ),完全功能模式,图形界面;6
:重启, reboot ;
3
, 5
。 级别切换: init n
。 级别查看: who -r
, runlevel
。
配置文件
各类型的init
配置文件存放路径为:
SysV init
:/etc/inittab
;Upstart
:/etc/inittab
,/etc/init/*.conf
;Systemd
:/usr/lib/systemd/system/
,/etc/systemd/system/
;
id:runlevels:action:process
# id :一个任务的标识符;
# runlevels :在哪些级别启动此任务;#,###,也可以为空,表示所有级别;
# action :在什么条件下启动此任务;
# wait :等待切换至此任务所在的级别时执行一次;
# respawn :一旦此任务终止,就自动重新启动之;
# initdefault :设定默认运行级别;此时, process 省略;
# sysinit :设定系统初始化方式,此处一般为指定 /etc/rc.d/rc.sysinit 脚本(此脚本主要用来完成整个系统初始化);
# process :任务;
例如:
# 设定默认运行级别为 3
id:3:initdefault:
# 设定系统初始化方式
si::sysinit:/etc/rc.d/rc.sysinit
# 每个运行级别切换时,执行对应的 rc 脚本
l0:0:wait:/etc/rc.d/rc 0
l1:1:wait:/etc/rc.d/rc 1
...
l6:6:wait:/etc/rc.d/rc 6
/etc/rc.d/rc.sysinit
rc.sysinit
是系统初始化脚本,由 init
进行优先调用以进行系统初始化,其主要实现的功能为:
- 设置主机名;
- 设置欢迎信息;
- 激活 udev 和 selinux ;
- 挂载 /etc/fstab 文件中定义的所有文件系统;
- 检测根文件系统,并以读写方式重新挂载根文件系统;
- 设置系统时钟;
- 根据 /etc/sysctl.conf 文件来设置内核参数;
- 激活 lvm 及软 raid 设备;
- 激活 swap 设备;
- 加载额外设备的驱动程序;
- 清理操作;
chkconfig
很多应用在安装时,都会生成一个服务脚本到/etc/init.d/
目录下,以便使用 service
命令进行控制。 chkconfig
,就是管控 /etc/init.d/
下每个服务脚本在各级别下的启动或关闭状态的命令。 能被添加进自启动服务的服务脚本,需要在开头添加 chkconfig
定义,比如:
#!/bin/sh
# chkconfig: 2345 80 05
# 2345 为启动 level
# 80 为启动优先权; 05 为停止优先权
# description: Starts and Stops the tomcatSvr daemon.
定义好的服务脚本,在执行 chkconfig name [on|off]
时,会按脚本内的启动 level ,创建超链接到各自的 /etc/rc.d/rc${level}.d/
目录中。( K 开头为要停止的服务,后面的数字为优先级,数字越小,越是优先关闭,依赖的服务先关闭,而后关闭被依赖的; S 开头的为要启动的服务,后面的数字为优先级,数字越小,越是优先启动,被依赖的服务先启动,而依赖的服务后启动。) chkconfig
常用参数:
# 查看
chkconfig --list
# 让服务受 chkconfig 管理(添加管理后, chkconfig 可对 level 进行修改)
chkconfig --add name
# 从 chkconfig 管理中删除服务
chkconfig --del name
# 管理服务
chkconfig [--level ] [--type ]
第六步:启动应用服务( /etc/rc.d/rc
)
通过前面的说明可以知道, /etc/rc.d/rc${level}.d/
目录中存放了各种需要在不同的 level 下需要启动或关闭的服务脚本超链接,在系统初始化结束后,便会调用 /etc/rc.d/rc
脚本,带入运行级别,去执行各 level 目录下的脚本。 其脚本实现框架为:
for srv in /etc/rc.d/rc${level}.d/K*; do
$srv stop
done
for srv in /etc/rc.d/rc${level}.d/S*; do
$srv start
done
# 其中 level 参数为外部带入。
正常级别下(2345),系统执行完 /etc/rc.d/rc${level}.d/
目录下的脚本后,都会去执行 /etc/rc.d/rc.local
脚本,因此,不便或不需写为服务脚本的程序期望能开机自动运行时,直接放置于此脚本文件中即可。
[hzz@magedu ~]$ find /etc/rc.d/ -name "*local" -type l -exec ls -l {} \;
lrwxrwxrwx. 1 root root 11 8月 24 09:59 /etc/rc.d/rc5.d/S99local -> ../rc.local
lrwxrwxrwx. 1 root root 11 8月 24 09:59 /etc/rc.d/rc2.d/S99local -> ../rc.local
lrwxrwxrwx. 1 root root 11 8月 24 09:59 /etc/rc.d/rc3.d/S99local -> ../rc.local
lrwxrwxrwx. 1 root root 11 8月 24 09:59 /etc/rc.d/rc4.d/S99local -> ../rc.local
[hzz@magedu ~]$
第七步:启动终端
系统初始化完成后, init 给出用户登录提示符( login )或者图形化登录界面,用户输入用户和密码登陆后,系统会为用户分配一个用户 ID ( uid )和组 ID ( gid ),这两个 ID 是用户的身份标识,用于检测用户运行程序时的身份验证。登录成功后,整个系统启动流程运行完毕!其他
前面所说的初始化,大多是以SysV init
为蓝本的,因为其兼容性最高,但也说到 CentOS 6/7
使用的是完全不同的机制,现在简要说说区别。 CentOS 6 : 使用的 init 程序是 upstart
,但其执行脚本依然命名为 /etc/init
。 其配置文件: /etc/init/*.conf
( *.conf
为 upstart
风格的配置文件), /etc/inittab
(仅用于定义默认运行级别)。 CentOS 7 : init 程序为 systemd
。 配置文件: /usr/lib/systemd/system/
, /etc/systemd/system/
。 虽然 init 程序和配置文件已经是完全不同的两种风格了,但是完全兼容 SysV
脚本机制。 因此, service
命令依然可用,不过建议使用 systemctl
命令来控制服务:
systemctl {start|stop|restart|status} name[.service]