系统启动可以分为以下六个阶段:BIOS, MBR, GRUB, Kernel, Init, Runlevel

linux-boot-process

BIOS

BIOS(基本输入输出系统),是计算机启动时加载的第一个软件。

计算机在通电后首先由BIOS对自身的硬件环境进行自检,这就是POST(Power On Self Test开机自检),这个过程主要是硬件环境自检,例如检查CPU, 内存, 主板等设备是否有故障存在。

在引导系统启动时,BIOS会按照CMOS中设置的顺序来选择可以引导系统启动设备(CD-ROM,硬盘上的某个分区,USB设备,网络上的某个设备等)。

系统启动时一般都是从硬盘上引导的,引导程序位于磁盘的首个扇区上的MBR(主引导记录),在磁盘上的三维地址为(0磁道,0柱面,1扇区)。 MBR内的信息可以通过任何一种基于某种操作系统的分区工具软件写入,但和某种操作系统没有特定的关系,即只要创建了有效的主引导记录就可以引导任意一种操作系统。MBR记录硬盘本身的相关信息以及硬盘各个分区的大小及位置信息,是数据信息的重要入口。

当MBR中的引导程序被加载到内存后,BIOS把控制权交给MBR,由MBR继续引导系统启动。

MBR

MBR(主引导记录,主引导扇区)是由Boot loader(446个字节), Partition table(64个字节), Magic Number(2个字节)组成。 MBR加载完成后,将由系统引导程序继续引导系统启动。

GRUB

GRUB即GRand Unified Bootloader,它负责装载内核并将控制权转交。 如果系统上安装了多个内核映像,则可以选择其中一个来执行,会显示一个启动画面,如果你不输入任何东西,则会加载grub配置文件中指定的默认内核映像。

CentOS7使用的引导程序是grub2,在加载数据并开始读取grub2的引导时会读取/boot/grub2/grub.cfg的相关配置。/etc/grub2.cfg是/boot/grub2/grub.cfg的文件链接。

在grub2.cfg中搜索initrd,可以看到内核和initrd镜像。

1grep initrd /etc/grub2.cfg
2        initrd16 /initramfs-3.10.0-327.el7.x86_64.img
3        initrd16 /initramfs-0-rescue-38805434c054469dbb992bc805a55451.img

Kernel

系统启动进入内核映像加载阶段,initrd是一个临时的文件系统,在启动阶段被内核调用,作为临时根文件系统,直到真正的根文件系统被挂载。

内核初始化的最后一步就是运行/sbin/init程序。linux中有很多init系统,如传统的sysvinit,Unbuntu从6.1开始使用upstart,CentOS7的systemd等等。

Init

init进程取得系统控制权后,会根据默认的运行级别来初始化该运行级别下相关的服务。。

CentOS 7使用systemd替换了使用多年的sysvinit。 CentOS 7下可以看到/sbin/init是/lib/systemd/systemd的文件链接/sbin/init -> ../lib/systemd/systemdps -ef | grep systemd可以看到它的pid为1,即为init进程。

系统运行级别:

  • 0 - 关机: 运行级别设置成0,开机后就会进入关机状态。当运行级别切换到0时,会立即停止正在运行的服务,并关闭系统电源。
  • 1 - 单用户模式: 无网络链接,不运行守护进程。主要用于系统的维护,只允许root用户登录。
  • 2 - 本地多用户模式: 无网络链接,不运行守护进程。
  • 3 - 完全多用户文本模式: 正常启动系统及相关服务。
  • 4 - 用户自定义: 保留,未使用,主要是为开发人员定制功能,例如用于单片机或其他系统的开发和应用。
  • 5 - 多用户图形系统: 该模式与3基本相同,除了文本模式之外还有图形界面
  • 6 - 重启: 该级别是系统重启模式,系统在进入该级别后会立即重新启动

在CentOS7中systemd使用targets替代了运行级别,可以使用下面的命令查看。

1systemctl get-default
2multi-user.target

init进程在获取/etc/systemd/system/default.target文件中关于系统运行级别的参数后,将执行相关的脚本对键盘、字体、装载模块、网络设置等进行初始化。

Runlevel

接下来要执行runlevel相关的程序,根据默认的系统运行级别,系统会执行/etc/rc.d/rc*.d下的文件。

系统在运行级别2-5下会把/etc/rd.d/rc.local文件作为系统初始化的最后一个脚本。有的时候为了避免编写启动脚本的麻烦,可以在这个文件中添加开机启动的命令。但如果系统使用systemd作为init系统,还是推荐编写systemd服务文件,放到/usr/lib/systemd/system下面。

用户环境初始化

在系统完成启动后会执行后,会执行/bin/login启动用户登录界面,在用户登录到系统后,通过系统通过/etc/profile文件来为每个用户初始化环境。如果/etc/profile中的变量参数只希望对某一个用户的环境起作用,可以在/etc/profile通过if条件来实现。

如果用户登录到系统使用的shell是bash,在执行完/etc/profile脚本之后还会执行~/.bash_profile文件,之后会执行~/.bashrc文件定义一些命令的别名,./bashrc文件中最后会检查是否存在/etc/bashrc文件,如果存在就会执行这个文件。

参考