Linux启动流程
Linux的启动流程包括了:
- 加载BIOS(Basic Input Output System)的硬件信息与进行自检(Power-On Self Test),并根据BIOS设置取得第一个可启动的设备
- 读取并执行第一个启动设备内MBR(Master Boot Record)的启动引导程序(一般是grub2)
- 根据启动引导程序的设置加载Kernel,Kernel会开始检测硬件与加载驱动程序
- 在硬件驱动成功后,Kernel会主动调用systemd程序,并以default.target准备操作系统
- systemd执行sysinit.target初始化系统及basic.target准备操作系统
- systemd启动multi-user.target下的本机与服务器服务
- systemd执行multi-user.target下的/etc/rc.d/rc.local文件
- systemd执行multi-user.target下的getty.target及登录服务
- systemd执行graphical需要的服务
当由boot loader读取内核文件后,Linux会将内核解压缩到内存当中,并且利用内核的功能,开始测试与驱动各个周边设备,包括存储设备、CPU、网卡、声卡等。此时Linux内核会以自己的功能重新检测一遍硬件,而不一定会使用BIOS检测到的硬件信息。内核文件一般会被放置到/boot里,取名为/boot/vmlinuz。
Linux内核是可以通过动态加载内核模块的(类似驱动程序),这些内核模块就放置在/lib/modules/目录内。由于模块放置到磁盘根目录内,因此在启动的过程中内核必须要挂载根目录,这样才能够读取内核模块提供的加载驱动程序功能。
虚拟文件系统(Initial RAM Disk或Initial RAM Filesystem)一般名为/boot/initrd或/boot/initramfs,这个文件的特色是它能够通过boot loader加载到内存中,然后这个文件会被解压缩并且在内存当中模拟成一个根目录,通过该程序来加载启动过程中所最需要的内核模块,通常这些模块就是USB、RAID等文件系统与磁盘接口的驱动程序。
systemd
内核加载完毕、进行完硬件检测与驱动程序加载后,内核会主动调用第一个程序,即systemd。systemd最主要的功能是准备软件执行的环境,包括系统的主机名、网络设置、语言设置、文件系统格式及其他服务的启动等。而所有的操作都会通过systemd的默认启动服务集合,即是/etc/systemd/system/default.target来规划。
default.target
CenOS 7的systemd启动流程是这样的:
- local-fs.target +swap.target:这两个target主要在挂载本机/etc/fstab里面所规范的文件系统与相关的内存交换分区。
- sysinit.target:这个target主要是检查硬件,加载所需要的内核模块等操作。
- basic.target:加载主要的外围硬件驱动程序与防火墙相关任务。
- multi-user.target:其他一般系统或网络服务的加载。
- 图形界面相关服务如gdm.service等其他服务的加载。
sysinit.target
- 特殊文件系统设备的挂载:如dev-hugepages.mount、dev-mqueue.mount等挂载服务,主要在挂载跟内存分页使用与消息队列功能。
- 特殊文件系统的启用:包括磁盘阵列、网络驱动器、LVM文件系统、文件系统对照服务等
- 启动过程的信息传递与动画执行
- 日志式日志文件的使用:启用systemd-journald
- 加载额外的内核模块
- 加载额外的内核参数设置
- 启动系统的随机数生成器
- 启动动态设备管理器。
basic.target
- 加载音效驱动程序
- 加载firewalld防火墙
- 加载CPU的微指令功能
- 启动与设置SELinux的安全上下文
- 将目前的启动过程所产生的启动信息写入到/var/log/dmesg当中
- 由/etc/sysconfig/modules/*.modules及/etc/rc.modules加载管理员指定的模块
- 加载systemd支持的timer功能
multi-user.target
一般服务的启动脚本设置都是放在下面的目录内:
- /usr/lib/systemd/system(系统默认的服务启动脚本设置)
- /etc/systemd/system(管理员自己开发与设置的脚本设置)
兼容SystemV的rc-local.service
提供tty界面与登录的服务
graphical.target
如果default.target是Multi-user.target的话,这个步骤不会执行。反之会开始加载图形界面。
内核与内核模块
内核都具有可读取模块化驱动程序的功能。
- 内核:/boot/vmlinuz或/boot/vmlinuz-version
- 内核解压缩所需RAM Disk:/boot/initramfs(/boot/initramfs-version)
- 内核模块:/lib/modules/version/kernel或/lib/modules/$(uname -r)/kernel
boot loader:grub2
grub2是目前Linux最主流的boot loader。 MBR是整个硬盘的第一个扇区中的一个区块,充其量整个大小也才446B。Linux将boot loader的程序代码执行与设置值加载分成了两个阶段。 grub2优点:
- 识别与支持较多的文件系统,并且可以使用grub2的主程序直接在文件系统中查找内核文件
- 启动时可以自行编辑与修改启动设置选项
- 可以动态查找配置文件,而不需要在修改配置文件后重新安装grub2
阶段一,执行boot loader主程序
MRR或者启动扇区仅安装boot loader的最小主程序
阶段二,主程序加载配置文件
通过boot loader加载所有配置文件与相关的环境参数文件(包括文件系统定义与主要配置文件grub.cfg),一般来说这些配置文件都放在/boot下面。
grub2配置文件维护
grub2官方不建议手动修改grub2配置文件,而是通过
/etc/default/grub
环境配置文件与/etc/grub.d
目录内的相关配置文件来处理。cat /etc/default/grub # 指定默认倒数读秒的秒数,不想等待输入0,一定让用户选择输入-1 GRUB_TIMEOUT=5 GRUB_DISTRIBUTOR="$(sed 's, release .*$,,g' /etc/system-release)" # 指定默认由哪一个选项来启动 GRUB_DEFAULT=saved # 是否要隐藏此选项,通常是藏起来比较好 GRUB_DISABLE_SUBMENU=true # 数据输出的终端格式,默认是通过命令行界面 GRUB_TERMINAL_OUTPUT="console" # menuentry括号内的Linux16后接的内核参数 GRUB_CMDLINE_LINUX="crashkernel=auto biosdevname=0 net.ifnames=0 rhgb quiet" # 取消恢复选项的制作 GRUB_DISABLE_RECOVERY="true"
配置完
/etc/default/grub
后执行grub2-mkconfig
来重建grub.cfginitramfs
内核模块放置于
/lib/modules/$(uname -r)/kernel
当中,这些模块必须要根目录(/)被挂载时才能够被读取。initramfs可以将/lib/modules/
内的启动过程中需要的模块包成一个文件,然后在启动时通过主机的INT 13硬件中断功能将该文件读出来解压缩,并且initramfs在内存内会模拟成为根目录,因此我们的内核最后就能识别实际的磁盘,那就能进行实际根目录的挂载。所以initramfs内所包含的模块大多是与启动过程有关,而主要以文件系统及硬盘模块为主。
需要initramfs的时刻为:
- 根目录所在磁盘为SATA、USB、SCSI等接口设备
- 根目录所在文件系统为LVM、RAID等特殊格式
- 根目录所在文件系统为非传统Linux支持的文件系统
- 其他必须要在内核加载时提供的模块