10.Linux 系统启动原理
Linux 系统启动原理
一、基础启动阶段(硬件到内核加载)
-
- 开机自检(BIOS)
- 按下电源后,计算机首先执行 BIOS(基本输入输出系统) 程序,作用是检测内存、CPU、硬盘等硬件是否正常,确保硬件具备启动条件,是启动流程的 “硬件体检环节”。
-
- MBR 引导
- BIOS 完成自检后,会读取硬盘 MBR(主引导记录) 分区的引导程序。MBR 是硬盘的第一个扇区,负责找到并加载系统分区的启动文件,是 “硬件与系统的衔接点”。
-
- GRUB 菜单
- MBR 引导后,进入 GRUB(Grand Unified Bootloader) 启动菜单,可选择不同内核版本(多内核环境下),决定加载哪个 Linux 内核(kernel),是 “内核选择环节”。
-
- 加载内核(kernel)
- GRUB 选定内核后,将 Linux 内核 加载到内存,内核开始接管系统,负责硬件驱动、进程管理等核心功能,是 “系统核心启动点”。
二、初始化与服务启动(systemd 主导)
-
- 运行 systemd 进程
- 内核加载完成后,启动 systemd 进程(Linux 系统的第一个进程,PID=1),它是现代 Linux 系统的 “初始化守护进程”,统一管理系统启动、服务、关机等流程。
-
- 根据 target 选择启动级别
- systemd 通过
/etc/systemd/system/default.target
文件,决定系统进入哪种 启动级别(target) 。target
是 systemd 对 “运行模式” 的定义(类似传统 SysVinit 的运行级别),比如multi-user.target
(多用户命令行模式)、graphical.target
(图形界面模式)。
-
- 系统初始化脚本
- 依据
target
,systemd 会执行/usr/lib/systemd/system/sysinit.target
关联的初始化脚本,完成系统基础配置(如挂载文件系统、设置环境变量等)。
-
- 定义开机启动服务
- systemd 读取
/etc/systemd/system
目录下的配置,加载并启动 开机服务(如网络服务、数据库服务等),这些服务以.service
文件定义,决定系统启动后自动运行哪些程序。
-
- 启动 mingetty 进程
- 最后,启动 mingetty(或类似终端进程),为用户提供命令行登录界面(字符终端环境);如果是图形界面
target
,会额外启动图形服务(如 Xorg、桌面环境)。
三、启动级别(target)说明
流程图左侧列出了常见的 systemd target 启动级别 ,对应不同运行场景:
poweroff.target
:关机模式(系统准备关机)。rescue.target
:救援模式(单用户、基础环境,用于修复系统)。multi-user.target
:多用户命令行模式(无图形界面,服务器常用)。graphical.target
:图形界面模式(含多用户 + 图形环境,桌面系统常用)。reboot.target
:重启模式(系统准备重启)。
Linux 系统的启动过程,就像一场精心编排的 “开机舞台剧”,每个角色按顺序登场,环环相扣,最终把系统从 “沉睡” 唤醒成 “待命” 状态。咱们一步步拆解这场 “演出”:
第一幕:电源接通 —— 硬件自检(BIOS/UEFI)
就像你早上被闹钟叫醒,先摸一摸自己:“胳膊腿还在不?脑子清醒不?”
- 电脑通电后,第一个 “说话” 的是BIOS/UEFI(相当于 “身体本能”),它会快速检查所有硬件:CPU、内存、硬盘、显卡…… 确认 “零件都在线,没坏”。
- 检查通过后,它会问:“系统装在哪块硬盘里?”(也就是找 “启动盘”,比如你设置的第一启动项是 SSD 还是机械硬盘)。找到后,就把 “接力棒” 交给硬盘的第一个特殊区域 ——MBR(主引导记录) 或 GPT 分区表(相当于硬盘上的 “启动指引牌”)。
第二幕:启动加载器登场(GRUB)
拿到接力棒的 MBR/GPT,会立刻喊出 “启动加载器”——GRUB(相当于 “管家”)。
- GRUB 会在屏幕上显示启动菜单(比如让你选 “正常启动 Linux” 还是 “进入救援模式”),就像管家问你:“今天想按哪种方式启动系统呀?”
- 你选好后,GRUB 会找到 Linux 的 “核心程序”——内核(vmlinuz) 和 “初始化内存盘”(initramfs),把它们加载到内存里。这一步就像管家帮你把 “系统核心工具包” 搬到桌子上,方便后续操作。
第三幕:内核 “掌权”—— 初始化硬件
内核被唤醒后,立刻接管系统,相当于 “新官上任”,先熟悉 “手下的兵”:
- 内核会启动自己的 “驱动程序”,识别并管理所有硬件(硬盘、网卡、鼠标等),就像新市长上任先摸清城市里的道路、水电、通讯设施。
- 然后,内核会把 “初始化内存盘” 里的临时工具释放掉(因为硬件已经识别完了,临时工具没用了),并找到根目录(/)所在的分区,准备进入下一步。
第四幕:初始化系统 —— 搭建运行环境(systemd)
内核准备好后,会启动第一个 “系统服务总管”——systemd(相当于 “大管家”,负责统筹所有服务)。
- systemd 的工作是 “搭建舞台”:启动网络服务、挂载硬盘分区、启动防火墙、设置时区…… 就像演唱会前,工作人员要接好电线、调好音响、摆好座椅,确保观众(用户)进来时一切就绪。
- 它会按 “优先级” 启动各种服务:先启动最基础的(比如文件系统挂载),再启动次要的(比如数据库、Web 服务),还会在屏幕上显示启动进度(就是你看到的那些 [OK] 或 [Failed] 的提示)。
第五幕:登录界面 —— 等待用户登场
当 systemd 把所有必要服务都启动完,就会启动 “登录管理器”(比如 gdm、lightdm),弹出用户名密码输入框,相当于 “舞台灯光亮起,等待观众入场”。
- 你输入密码登录后,就能看到桌面或命令行界面,此时整个系统完全启动,就像演唱会正式开始,你可以 “指挥” 系统干活了(打开软件、运行程序等)。
总结一下:
整个过程就像:
被闹钟叫醒(BIOS 自检)→ 找到衣服(GRUB 选内核)→ 穿好衣服(内核启动)→ 收拾房间(systemd 初始化)→ 开门迎客(登录界面)
每一步都缺一不可,任何一个环节出错(比如硬件坏了、GRUB 配置错了),“演出” 就会中断,系统也就启动失败啦~
系统 target
在 Linux 系统中,“系统 target”(systemd target)可以理解为 “系统状态的‘预设场景模式’”,就像手机里的 “飞行模式”“静音模式”“省电模式”—— 每种模式对应一组特定的服务组合,切换 target 就相当于切换系统的 “工作状态”。
为什么需要 target?
想象一下:你的电脑有时需要 “正常办公”(启动所有服务),有时需要 “临时修复故障”(只启动核心服务),有时需要 “关机休息”。总不能每次都手动一个个开 / 关服务吧?
systemd 用 target 把这些场景 “打包”,每个 target 关联了一堆服务(比如网络服务、桌面服务、登录服务等),切换 target 时,系统会自动启动 / 停止对应的服务,快速进入指定状态。
常见的 target 就像 “生活场景”:
- graphical.target(图形界面模式)
相当于 “家庭娱乐模式”:启动显卡驱动、桌面环境(GNOME/KDE)、鼠标键盘支持、网络服务…… 适合普通用户日常操作,就像打开电视、音响、游戏机,全家可以轻松用电脑。 - multi-user.target(多用户命令行模式)
相当于 “办公高效模式”:只启动命令行界面、网络服务、SSH 远程登录等核心功能,不加载图形界面(省资源)。适合服务器或需要远程管理的场景,就像办公室只开电脑主机和显示器,不接音箱、打印机,专注处理数据。 - rescue.target(救援模式)
相当于 “急诊室模式”:只启动最基础的服务(比如命令行、硬盘挂载),关闭大部分复杂功能。当系统出问题(比如启动失败、配置错误),可以进入这里排查修复,就像人生病了去急诊,只做必要的检查和治疗。 - poweroff.target(关机模式)
相当于 “睡眠模式”:系统会逐步停止所有服务,断开硬件连接,最后切断电源,让电脑 “休息”。
target 之间的关系:就像 “模式套娃”
有些 target 会 “包含” 其他 target,比如 graphical.target
会自动包含 multi-user.target
(先启动命令行基础,再叠加图形界面),而 multi-user.target
又会包含更基础的 basic.target
(基础服务)。
这就像 “豪华套餐” 里包含 “标准套餐”,“标准套餐” 里包含 “基础套餐”,一层套一层,确保服务启动有序。
如何切换 target?
用 systemctl
命令就像 “切换模式按钮”:
- 想进入图形界面:
systemctl isolate graphical.target
- 想切换到命令行:
systemctl isolate multi-user.target
- 想关机:
systemctl isolate poweroff.target
(其实就是poweroff
命令的底层原理)
简单说,systemd target 就是 Linux 系统的 “状态快捷方式”,让系统能根据需求快速切换到合适的工作模式,既灵活又高效~
systemd使用类型为target的单元来分组不同单元,例如multi-user.target包涵chronyd.service、crond.service、firewalld.service等服务。
target还可以包涵其他target,例如graphical.target包涵multi-user.target,multi-user.target包涵basic.target,basic.target包涵sysinit.target。
使用以下命令查看target之间依赖关系
[root@centos7 ~ 16:34:25]# systemctl list-dependencies graphical.target
graphical.target
● ├─accounts-daemon.service
● ├─gdm.service
● ├─initial-setup-reconfiguration.service
● ├─network.service
● ├─rtkit-daemon.service
● ├─systemd-readahead-collect.service
● ├─systemd-readahead-replay.service
● ├─systemd-update-utmp-runlevel.service
● ├─udisks2.service
● └─multi-user.target
● ├─abrt-ccpp.service
● ├─abrt-oops.service
● ├─abrt-vmcore.service
● ├─abrt-xorg.service
● ├─abrtd.service
● ├─atd.service
● ├─auditd.service
● ├─avahi-daemon.service
● ├─chronyd.service# 查看反向依赖
[root@centos7 ~ 16:36:19]# systemctl list-dependencies sshd.servive --reverse
sshd.servive.service
设置系统当前运行 target
[root@centos7 ~ 16:36:29]# systemctl isolate multi-user.target
[root@centos7 ~ 16:38:00]# systemctl isolate graphical.target #设置系统开机默认运行 target
[root@centos7 ~ 16:38:29]# systemctl get-default
graphical.target
[root@centos7 ~ 16:39:31]# systemctl set-default multi-user.target
Removed symlink /etc/systemd/system/default.target.
Created symlink from /etc/systemd/system/default.target to /usr/lib/systemd/system/multi-user.target.
系统启动级别
CentOS 6 之前使用启动级别控制系统开机激活哪些服务。CentOS 7 使用target控制系统开机激活哪些服务。
runlevel | target | 作用 |
---|---|---|
0 | 关机,init 0 同 poweroff 和systemctl poweroff | |
1 | emergency.target rescue.target | 单用户模式、救援模式和紧急模式用于修复系统 |
2 | 多用户文本界面,不具备NFS功能 | |
3 | multi-user.target | 多用户文本界面 |
4 | 未使用 | |
5 | graphical.target | 多用户图形界面 |
6 | 重启,init 6 同 reboot 和systemctl reboot |
重置 ROOT 密码
方法1:rd.break
-
重新启动系统。
-
按任意键(Enter除外)中断启动加载器倒计时。
-
将光标移至要启动的内核条目。
-
按e编辑选定的条目。
-
将光标移到内核命令行(以linux开头的行)。附加 rd.break。利用该选项,在系统从initramfs向实际系统移交控制权前,系统将会中断。
-
按Ctrl+x使用这些更改进行启动。
-
此时,系统会显示root shell,且磁盘上的实际根文件系统以只读方式挂载在/sysroot。
以读/写形式重新挂载/sysroot。
switch_root:/# mount -o remount,rw /sysroot
-
切换root位置,把/sysroot做为文件系统树的根。
switch_root:/# chroot /sysroot
-
设置新root密码。
sh-4.4# echo ‘’ | passwd --stdin root
方法2:init=/bin/bash
-
重新启动系统。
-
按任意键(Enter除外)中断启动加载器倒计时。
-
将光标移至要启动的内核条目。
-
按e编辑选定的条目。
-
将光标移到内核命令行(以linux开头的行)。
-
附加
init=/bin/bash
。利用该选项,在系统从initramfs向实际系统移交控制权前,系统将会中断,请开启一个root shell。 -
按Ctrl+x使用这些更改进行启动。
-
此时,系统会显示root shell,且磁盘上的实际根文件系统以只读方式挂载在/。
-
以读/写形式重新挂载/。
bash-4.4# mount -o remount,rw /
-
使用以下命令删除root密码,等进入系统后再重新设置root密码。
sh-4.4# passwd -d root
此时还可以使用vi编辑器直接编辑/etc/shadow文件,复制已知用户的密码记录替换root密码。
-
如果系统开启了SELinux功能,则需要确保所有未标记的文件(包括此时的/etc/shadow)在启动过程中都会重新获得标记。
sh-4.4# touch /.autorelabel
-
执行以下命令,系统将继续启动,执行完整的SELinux重新标记,然后再次重新启动。
sh-4.4# exec /usr/lib/systemd/systemd
-
使用root登录,此时不需要密码,使用 passwd 命令设置新的密码。
/etc/fstab 引起的系统启动问题
环境准备
[root@server ~ 10:03:57]# mkdir -p /data01
[root@server ~ 10:04:05]# echo '/dev/sdb1 /data01 xfs defaults 0 0
故障1:挂载点不存在
环境准备
[root@server ~ 10:04:25]# umount /data01
[root@server ~ 10:04:40]# rmdir /data01
重启系统验证
# 可以正常进入系统,挂载点会被自动创建
[root@server ~ 10:06:42]# df -h /data01
文件系统 容量 已用 可用 已用% 挂载点
/dev/sdb1 2.0G 33M 2.0G 2% /data01
故障2:设备名称写错或者找不到设备
环境准备
[root@server ~ 10:06:53]# vim /etc/fstab
# 将原先的sdb1修改为sdb2
[root@server ~ 10:14:28]# reboot
重启系统验证
-
重新启动系统。
-
按任意键(Enter除外)中断启动加载器倒计时。
-
将光标移至第一个内核条目,按e编辑当前条目。
-
将光标移至以 linux16 开头的行,末尾附加
rd.break
后回车。 -
将硬盘挂载到 sysroot,并提供rw权限,
mount -o remount,rw /sysroot
-
以root方式进入,
chroot /sysroot
-
进入到
/etc/fstab
,修改错误条目vi /sysroot
,修改完成后保存并退出。 -
exit,退出后继续启动。
故障3:破坏文件系统
环境准备
[root@server ~ 10:38:40]# dd if=/dev/zero of=/dev/sdb1 bs=1M count=1
记录了1+0 的读入
记录了1+0 的写出
1048576字节(1.0 MB)已复制,0.00119751 秒,876 MB/秒
[root@server ~ 10:41:48]# umount /data01
[root@server ~ 10:42:01]# mount /dev/sdb1 /data01
mount: 将 /dev/sdb1 挂载到 /data01 失败: 结构需要清理
重启系统验证
- 重启系统
- 以root方式进去
- 执行以下命令修复
- xfs_repair /dev/sdb1
#已成功挂载
[root@server ~ 10:46:49]# df -h /data01
文件系统 容量 已用 可用 已用% 挂载点
/dev/sdb1 2.0G 33M 2.0G 2% /data01
grub2 配置
grub2 配置文件
grub2 的主要配置文件如下:
-
/boot/grub2,grub2的主要配置文件所在目录,例如grub.cfg、grubenv、user.cfg。
-
/etc/grub2.cfg
-
/etc/grub2.cfg 是指向 /boot/grub2/grub.cfg的软连接。
-
不要直接修改/etc/grub2.cfg文件,该文件由系统自动生成。如果需要自定义这个文件,可以通过修改/etc/grub.d/中脚本和/etc/default/grub文件,然后通过grub2-mkconfig命令生成。
使用efi启动方式的grub2配置文件是/etc/grub2-efi.cfg。
-
-
/etc/grub.d/,该目录下存放多个数字开头的脚本,按照从小到大的顺序执行。例如00_header会调用/etc/default/grub配置文件来实现最基本的开机界面配置。
-
/etc/default/grub,定义grub启动部分变量信息,例如grub启动菜单选择条目的超时时间,内核参数等。
-
/boot/grub2/grubenv,设定默认启动条目。
grub 菜单超时时间
[root@server ~ 11:11:56]# vim /etc/default/grub
# 修改GRUB_TIMEOUT为10
GRUB_TIMEOUT=1
#生效grub2.cfg配置文件
[root@server ~ 11:14:17]# grub2-mkconfig -o /etc/grub2.cfg
#重启
kernel 启动参数
[root@server ~ 11:16:48]# vim /etc/default/grub
# 修改GRUB_CMDLINE_LINUX,例如在最后添加参数console=ttyS0,导致不显示启动过程
GRUB_CMDLINE_LINUX="rd.lvm.lv=centos/root rd.lvm.lv=centos/swap rhgb quiet console=ttyS0"
[root@server ~ 11:18:20]# grub2-mkconfig -o /etc/grub.cfg
Generating grub configuration file ...
Found linux image: /boot/vmlinuz-3.10.0-1160.71.1.el7.x86_64
Found initrd image: /boot/initramfs-3.10.0-1160.71.1.el7.x86_64.img
Found linux image: /boot/vmlinuz-0-rescue-cc2e2154e9c04abb980000c98990a8bd
Found initrd image: /boot/initramfs-0-rescue-cc2e2154e9c04abb980000c98990a8bd.img
done
grub 菜单加密
# 查看/etc/grub.d/01_users脚本
[root@server ~ 17:37:59]# cat /etc/grub.d/01_users
#!/bin/sh -e
cat << EOF
if [ -f \${prefix}/user.cfg ]; thensource \${prefix}/user.cfgif [ -n "\${GRUB2_PASSWORD}" ]; thenset superusers="root"export superuserspassword_pbkdf2 root \${GRUB2_PASSWORD}fi
fi
EOF
[root@server ~ 17:37:59]# grub2-mkpasswd-pbkdf2
Enter password: 123
Reenter password: 123
PBKDF2 hash of your password is grub.p......
# 创建文件
[root@server ~ 17:38:59]# vim /boot/grub2/user.cfg
GRUB2_PASSWORD=grub.....
# 生成grub2.cfg配置文件,重启验证
-
启动菜单界面,按e编辑。
-
输入用户名root,密码123
解除 grub 菜单加密:
使用光盘启动
1.开机从光盘启动,并选择Troubleshooting
。
2.选择Rescue a Rocky Linux system
3.稍等片刻,进入选择界面,选择 1
。搜索到系统后,提示系统已经挂载在/mnt/sysimage,按回车继续。
4.将文件移回去
mv http.xml /usr/lib/firewalld/services/http.xml
重启
systemctl reload firewalld.service