“你来说说linux系统的启动过程是什么样的?” ,这个问题相信大家经常听到,只要是linux系统知识相关的面试,很大概率面试官都会问到这个问题。那今天就来说明一下,对于linux系统来说,按下服务器开机键后,究竟发生了什么。以centos7为例,先通过一个图来看下从服务器开机到系统启动的过程
下面我们来一步步拆解,对于linux系统来说,从按下服务器电源键到系统完全启动究竟是怎样一个过程。
BIOS
bios为基本输入输出系统,主要负责两部分POST自检和加载MBR。
- POST自检:读取CMOS RAM中的信息来识别硬件配置并对硬件进行自检测试和初始化操作。
- 加载MBR:读取启动设备列表,从第一个可启动设备加载引导加载程序(如硬盘、光驱、USB设备等)
MBR
MBR即主引导记录,位于可启动设备(如磁盘)的第一个扇区,大小为512字节,最后两个字节以55AA结束。
当POST自检结束后,BIOS会将可启动设备的第一个扇区(MBR扇区)读入内存地址0000:7c00H处。接着会检查0000:01FEH到0000:01FFH这段地址的值是否为55AAH,如果不等于,则尝试其他启动设备。如果等于,BIOS将控制权交给相应的启动设备。MBR会将自身复制到内存0000:0600H处,然后根据MRB中的引导代码启动引导程序(即grub)
我们可以通过以下方式查看启动设备中的mbr信息
dd if=/dev/vda bs=512 count=1 | hexdump -C
通常来说,BIOS除了检查MBR的结束标志位是否等于55AAH外,还会检查磁盘是否有写保护、主引导扇区中是否存在活动分区等。
GRUB
grub是一个用于加载和管理系统启动的完整程序。最主要作用都是将内核加载到内存并运行。目前的linux发行版大都使用grub2取代了较旧的 grub引导加载程序。
grub由几个映像文件组成,引导镜像boot.img、内核映像kernel.img、核心镜像core.img。核心镜像由一组模块和kernel.img组成。我们在/boot/grub2/i386-pc/或/usr/lib/grub/i386-pc/目录下能看到相应的镜像和模块文件。
从leagcy模式下启动内核,bootloader至少包含两块二进制的程序代码,分别是boot.img与core.img。boot.img是grub启动的第一个程序,位于mgr的前446字节bootloader中。这块空间的大小使得boot.img程序能实现的功能有限,因此它无法理解文件系统,core.img的位置是硬编码在boot.img中的。boot.img中唯一做的事情就是读取core.img的第一个扇区,然后将控制权移交给core.img再由core.img来完成内核的加载操作。因为core.img的位置是硬编码在boot.img中的,所以如果移动了core.img在磁盘上的位置却没有重新生成boot.img的话,很可能会导致操作系统启动失败。
boot.img启动后会找到core.img扇区的地址,将它拷贝到0x8000处运行,同时通过biso中断读取到core.img里的kernel.img(前面提到过core.img由kernel.img和一些mod组成),然后将控制权交给kernel.img。
kernel.img会调用grub_load_modules()来加载各个mod模块,模块加载后就能识别文件系统了。接着kernel.img再调用grub_load_normal_mode()加载normal模块。normal模块会先读取并解析grub.cfg,接着再根据command.list定位并加载linux模块(/boot/grub2/i386-pc目录下)。下一步就是初始化屏幕显示、载入字体、展示grub菜单
grub2 配置文件位于 /boot/grub2/grub.cfg
kernel
grub会在 /boot 目录中搜索压缩的内核映像文件,通常称为 'vmlinuz'。这个文件包含内核的基本代码,是系统继续运行的前提。找到后,grub 将 vmlinuz 内核映像文件加载到内存中。随后,grub 解压 initramfs 映像文件的内容,建立一个基于内存的临时文件系统,称为 tmpfs。
initramfs是一个被压缩过的小型根目录,这个目录里包含了启动阶段中所必须的驱动模块、可执行文件以及启动脚本。当系统启动的时候,bootloader会把内核和initramfs⽂件读到内存中,然后把initramfs的起始地址告诉内核。
内核在运⾏过程中会解压initramfs,然后把initramfs挂载为根⽬录,然后执⾏根⽬录中的/initrc脚本,可以在这个脚本中运⾏initrd中的udevd,让它来⾃动加载设备驱动程序以及 在/dev⽬录下建⽴必要的设备节点。在udevd⾃动加载磁盘驱动程序之后,就可以mount真正的根⽬录,并切换到这个根⽬录中。接着系统的第一个进程systemd就启动了。
systemd
systemd 是所有进程的父进程。它负责将 Linux 主机带到一个用户可操作状态(可以执行功能任务)。Systemd 读取 /etc/systemd/system/default.target 链接的文件(例如 /usr/lib/systemd/system/multi-user.target)来确定默认系统目标(相当于运行级别)。同时systemd还会为系统做一些初始化工作
1. 设置主机名
2. 初始化网络
3. 根据配置初始化 seLinux
4. 打印欢迎横幅
5. 根据内核启动参数初始化系统硬件
6. 挂载文件系统,包括虚拟文件系统,如 /proc 文件系统
7. 清理 /var 中的目录
8. 启用swap
系统启动的第一个进程systemd
上面就是linux系统的整个启动流程,简单描述如下图
详细描述如下图
关注公众号 singless,获取更多有价值的文章