20220927 19. 开机流程、模块管理与 Loader
19.1 Linux 的开机流程分析
19.1.1 开机流程一览
系统开机的经过可以汇整成下面的流程的:
-
载入 BIOS 的硬件信息与进行自我测试,并依据设置取得第一个可开机的设备;
-
读取并执行第一个开机设备内 MBR 的 boot Loader (亦即是 grub2, spfdisk 等程序);
-
依据 boot loader 的设置载入 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 需要的服务
-
19.1.2 BIOS, boot loader 与 kernel 载入
专有名词
-
BIOS:不论传统 BIOS 还是 UEFI BIOS 都会被简称为 BIOS;
-
MBR:虽然分区表有传统 MBR 以及新式 GPT,不过 GPT 也有保留一块相容 MBR 的区 块,因此,下面的说明在安装 boot loader 的部份, 鸟哥还是简称为 MBR 喔!总之, MBR 就代表该磁盘的最前面可安装 boot loader 的那个区块就对了!
BIOS, 开机自我测试与 MBR/GPT
系统去载入 BIOS (Basic Input Output System),并通过 BIOS 程序去 载入 CMOS 的信息,并且借由 CMOS 内的设置值取得主机的各项硬件设置
BIOS 还会进行开机自我测试 (Power-on Self Test, POST)
BIOS 会指定开机的设备好让我们可以读取 磁盘中的操作系统核心文件。 但由于不同的操作系统他的文件系统格式不相同,因此我们必 须要以一个开机管理程序来处理核心文件载入 (load) 的问题, 因此这个开机管理程序就被 称为 Boot Loader 了。那这个 Boot Loader 程序安装在哪里呢?就在开机设备的第一个扇区 (sector) 内,也就是我们一直谈到的 MBR (Master Boot Record, 主要开机记录区)
Boot Loader 的功能
-
提供菜单:使用者可以选择不同的开机项目,这也是多重开机的重要功能!
-
载入核心文件:直接指向可开机的程序区段来开始操作系统;
-
转交其他 loader:将开机管理功能转交给其他 loader 负责。
BIOS 与 boot loader 及核心载入流程示意图
在核心完整的载入后,您的主机应该就开始正确的运行了,接下来,就是要开始执行系统的 第一支程序: systemd !
19.1.3 第一支程序 systemd 及使用 default.target 进入开机程 序分析
systemd 最主要的功能 就是准备软件执行的环境,包括系统的主机名称、网络设置、语系处理、文件系统格式及其 他服务的启动等。
而所有的动作都会通过 systemd 的默认启动服务集合,亦即是 /etc/systemd/system/default.target 来规划。
另外, systemd 已经舍弃沿用多年的 system V 的 runlevel 了喔!
常见的操作环境 target 与相容于 runlevel 的等级
可以作为默认的操作环境 (default.target) 的主要项目有: multi-user.target 以及 graphical.target 这两个。当然还有某些比较特殊的操作环境, 包括在第十七章里面谈到的 rescue.target, emergency.target, shutdown.target 等
过去的 systemV 使用的是一个称为 runlevel (执行等级) 的概念来启动系统的, systemd 为了相容于旧式的 systemV 操作行为, 所以也将 runlevel 与操作环境做个结合
# 查询两者间的对应
ll -d /usr/lib/systemd/system/runlevel*.target
SystemV | systemd |
---|---|
init 0 | systemctl poweroff |
init 1 | systemctl rescue |
init [234] | systemctl isolate multi-user.target |
init 5 | systemctl isolate graphical.target |
init 6 | systemctl reboot |
systemd 的处理流程
CentOS 7.x 的 systemd 开机流程大约是这样:
-
local-fs.target + swap.target:这两个 target 主要在挂载本机 /etc/fstab 里面所规范的文 件系统与相关的内存交换空间。
-
sysinit.target:这个 target 主要在侦测硬件,载入所需要的核心模块等动作。
-
basic.target:载入主要的周边硬件驱动程序与防火墙相关任务
-
multi-user.target 下面的其它一般系统或网络服务的载入
-
图形界面相关服务如 gdm.service 等其他服务的载入
19.1.4 systemd 执行 sysinit.target 初始化系统、basic.target 准备系统
systemctl list-dependencies sysinit.target
sysinit.target 有很多相 依的服务
-
特殊文件系统设备的挂载:包括 dev-hugepages.mount dev-mqueue.mount 等挂载服 务,主要在挂载跟巨量内存分页使用与讯息伫列的功能。 挂载成功后,会在 /dev 下面创 建 /dev/hugepages/, /dev/mqueue/ 等目录;
-
特殊文件系统的启用:包括磁盘阵列、网络磁盘 (iscsi)、LVM 文件系统、文件系统对 照服务 (multipath) 等等,也会在这里被侦测与使用到!
-
开机过程的讯息传递与动画执行:使用 plymouthd 服务搭配 plymouth 指令来传递动画与 讯息
-
日志式登录文件的使用:就是 systemd-journald 这个服务的启用啊!
-
载入额外的核心模块:通过 /etc/modules-load.d/*.conf 文件的设置,让核心额外载入管 理员所需要的核心模块!
-
载入额外的核心参数设置:包括 /etc/sysctl.conf 以及 /etc/sysctl.d/*.conf 内部设置!
-
启动系统的乱数产生器:乱数产生器可以帮助系统进行一些密码加密演算的功能
-
设置终端机 (console) 字形
-
启动动态设备管理员:就是 udevd 这个家伙!用在动态对应实际设备存取与设备文件名 对应的一个服务!相当重要喔!也是在这里启动的!
sysinit.target 在初始化系 统,而这个 basic .target 则是一个最简单的操作系统了!
basic.target 的阶段主要启动 的服务
-
载入 alsa 音效驱动程序:这个 alsa 是个音效相关的驱动程序,会让你的系统有音效产生 啰;
-
载入 firewalld 防火墙:CentOS 7.x 以后使用 firewalld 取代 iptables 的防火墙设置,虽然 最终都是使用 iptables 的架构, 不过在设置上面差很多喔!
-
载入 CPU 的微指令功能;
-
启动与设置 SELinux 的安全本文:如果由 disable 的状态改成 enable 的状态,或者是管 理员设置强制重新设置一次 SELinux 的安全本文, 也在这个阶段处理喔!
-
将目前的开机过程所产生的开机信息写入到 /var/log/dmesg 当中
-
由 /etc/sysconfig/modules/*.modules 及 /etc/rc.modules 载入管理员指定的模块!
-
载入 systemd 支持的 timer 功能;
在这个阶段完成之后,你的系统已经可以顺利的运行!就差一堆你需要的登陆服务、网络服 务、本机认证服务等等的 service 类别啰!
19.1.5 systemd 启动 multi-user.target 下的服务
在载入核心驱动硬件后,经过 sysinit.target 的初始化流程让系统可以存取之后,加上 basic.target 让系统成为操作系统的基础, 之后就是服务器要顺利运行时,需要的各种主机服 务以及提供服务器功能的网络服务的启动了。
这些服务的启动则大多是附挂在 multi-user.target 这个操作环境下面, 你可以到 /etc/systemd/system/multi-user.target.wants/ 里头 去瞧瞧默认要被启动的服务喔!
一般来说服务的启动脚本设置都是放在下面的目录内:
-
/usr/lib/systemd/system (系统默认的服务启动脚本设置)
-
/etc/systemd/system (管理员自己开发与设置的脚本设置)
而使用者针对主机的本机服务与服务器网络服务的各项 unit 若要 enable 的话,就是将它放到 /etc/systemd/system/multi-user.target.wants/ 这个目录下面做个链接~ 这样就可以在开机的 时候去启动他。
[root@study ~]# systemctl disable vsftpd.service
rm '/etc/systemd/system/multi-user.target.wants/vsftpd.service'
[root@study ~]# systemctl enable vsftpd.service
ln -s '/usr/lib/systemd/system/vsftpd.service' '/etc/systemd/system/multi-user.target.wants/vsftpd.service'
这些程序除非在脚本设置里面原本就有规范服务的相依性, 这 样才会有顺序的启动之外,大多数的服务都是同时启动的!这就是 systemd 的多任务
相容 systemV 的 rc-local.service
过去用过 Linux 的朋友大概都知道,当系统完成开机后,还想要让系统额外执行某些 程序的话,可以将该程序指令或脚本的绝对路径名称写入到 /etc/rc.d/rc.local 这个文件去!
新 的 systemd 机制中,它建议直接写一个 systemd 的启动脚本配置文件到 /etc/systemd/system 下面,然后使用 systemctl enable 的方式来设置启用它,而不要直接使用 rc.local 这个文件 啦!
systemd 仍然支持之前的机制,那就是 rc-local.service 这个服务的功能了!
# 1\. 先看一下 /etc/rc.d/rc.local 的权限,然后检查 multi-user.target 有没有这个服务
[root@study ~]# ll /etc/rc.d/rc.local
[root@study ~]# systemctl status rc-local.service
# 2\. 加入可执行权限后,再看一下 rc-local 是否可被启用!
[root@study ~]# chmod a+x /etc/rc.d/rc.local; ll /etc/rc.d/rc.local
[root@study ~]# systemctl daemon-reload
[root@study ~]# systemctl list-dependencies multi-user.target | grep rc-local
提供 tty 界面与登陆的服务
在 multi-user.target 下面还有个 getty.target 的操作界面项目喔!
能不能提供适当的登陆服务也是 multi-user.target 下面的内容!包括 systemd-logind.service, systemd-user-sessions.service 等服务。
由于服务都是同步运行,不一定哪个服务先启动完毕。如果 getty 服务先 启动完毕时,你会发现到有可用的终端机尝试让你登陆系统了。 问题是,如果 systemd- logind.service 或 systemd-user-sessions.service 服务尚未执行完毕的话,那么你还是无法登 陆系统的。
19.1.6 systemd 启动 graphical.target 下面的服务
如果你的 default.target 是 multi-user.target 的话,那么这个步骤就不会进行。反之,如果是 graphical.target 的话,那么 systemd 就会开始载入用户管理服务与图形界面管理员 (window display manager, DM) 等,启动图形界面来让用户以图形界面登陆系统喔!
[root@VM-72-146-centos ~]# systemctl list-dependencies graphical.target
graphical.target
● ├─display-manager.service
● ├─irqaffinity.service
● ├─mysqld.service
● ├─network.service
● ├─redis.service
● ├─systemd-update-utmp-runlevel.service
● └─multi-user.target
● ├─acpid.service
● ├─atd.service
...
...
比 multi-user.target
多出的这些服务,大多数都是图形界面帐号管理的功能,至于实 际让用户可以登陆的服务,倒是那个 gdm.service
去瞧瞧 gdm.service 的内容, 就会发现最重要的可执行文件是 /usr/sbin/gdm
到此为止,systemd 就已经完整的处理完毕,你可以使用图形界面或文字界面的方式来登陆 系统,系统也顺利的开机完毕, 也能够将你写入到 /etc/rc.d/rc.local 的脚本实际执行一次啰。
19.1.7 开机过程会用到的主要配置文件
关于模块
有两 个地方可以处理模块载入的问题,包括:
-
/etc/modules-load.d/*.conf:单纯要核心载入模块的位置;
-
/etc/modprobe.d/*.conf:可以加上模块参数的位置
我们可能需要修改防火墙设置,其中一个针对 FTP 很重要的防火墙模块 为 nf_conntrack_ftp, 因此,你可以将这个模块写入到系统开机流程中,例如:
[root@study ~]# vim /etc/modules-load.d/vbird.conf
nf_conntrack_ftp
一个模块 (驱动程序) 写一行~然后,上述的模块基本上是针对默认 FTP 端口,亦即 port 21 所设置的,如果需要调整到 port 555 的话, 得要外带参数才行!模块外加参数的设置方式 得要写入到另一个地方喔!
[root@study ~]# vim /etc/modprobe.d/vbird.conf
options nf_conntrack_ftp ports=555
之后重新开机就能够顺利的载入并且处理好这个模块了。不过,如果你不想要开机测试,想 现在处理呢?
[root@study ~]# lsmod | grep nf_conntrack_ftp
[root@study ~]# systemctl restart systemd-modules-load.service
[root@study ~]# lsmod | grep nf_conntrack_ftp
/etc/sysconfig/*
-
authconfig: 这个文件主要在规范使用者的身份认证的机制,包括是否使用本机的 /etc/passwd, /etc/shadow 等, 以及 /etc/shadow 密码记录使用何种加密演算法,还有是 否使用外部密码服务器提供的帐号验证 (NIS, LDAP) 等。 系统默认使用 SHA512 加 密演算法,并且不使用外部的身份验证机制;另外,不建议手动修改这个文件喔!你应 该使用“ authconfig-tui ”指令来修改较佳!
-
cpupower: 如果你有启动 cpupower.service 服务时,他就会读取这个配置文件。主要是 Linux 核心如何操作 CPU 的原则。 一般来说,启动 cpupower.service 之后,系统会让 CPU 以最大性能的方式来运行,否则默认就是用多少算多少的模式来处理的。
-
firewalld, iptables-config, iptables-config, ebtables-config: 与防火墙服务的启动外带的 参数有关
-
network-scripts/: 至于 network-scripts 里面的文件,则是主要用在设置网卡
19.2 核心与核心模块
在整个开机的过程当中,是否能够成功的驱动我们 主机的硬件配备, 是核心 (kernel) 的工作!而核心一般都是压缩文件,因此在使用核心之 前,就得要将他解压缩后,才能载入内存当中。
为了应付日新月异的硬件,目前的核心都是具有“可读取模块化驱动程序”的功能, 亦 即是所谓的“ modules (模块化)”的功能啦!所谓的模块化可以将他想成是一个“外挂程序”, 该外挂程序可能由硬件开发厂商提供,也有可能我们的核心本来就支持~不过,较新的硬 件, 通常都需要硬件开发商提供驱动程序模块啦!
核心与核心模块放在哪?
-
核心: /boot/vmlinuz 或 /boot/vmlinuz-version;
-
核心解压缩所需 RAM Disk: /boot/initramfs (/boot/initramfs-version);
-
核心模块: /lib/modules/version/kernel 或 /lib/modules/$(uname -r)/kernel;
-
核心源代码: /usr/src/linux 或 /usr/src/kernels/ (要安装才会有,默认不安装)
如果该核心被顺利的载入系统当中了,那么就会有几个信息纪录下来:
-
核心版本:/proc/version
-
系统核心功能:/proc/sys/kernel/
如果我有个新的硬件,偏偏我的操作系统不支持,该怎么办?
-
重新编译核心,并加入最新的硬件驱动程序源代码;
-
将该硬件的驱动程序编译成为模块,在开机时载入该模块
19.2.1 核心模块与相依性
核心模块的放置处是在 /lib/modules/$(uname -r)/kernel 当中,里面主要还分成几个目录:
-
arch :与硬件平台有关的项目,例如 CPU 的等级等等;
-
crypto :核心所支持的加密的技术,例如 md5 或者是 des 等等;
-
drivers :一些硬件的驱动程序,例如显卡、网卡、PCI 相关硬件等等;
-
fs :核心所支持的 filesystems ,例如 vfat, reiserfs, nfs 等等;
-
lib :一些函数库;
-
net :与网络有关的各项协定数据,还有防火墙模块 (net/ipv4/netfilter/*) 等等;
-
sound :与音效有关的各项模块;
Linux 当然会提供一些模块相依性的解决方案,那就是检 查/lib/modules/$(uname -r)/modules.dep 这个文件
[root@www ~]# depmod [-Ane]
选项与参数:
-A :不加任何参数时, depmod 会主动的去分析目前核心的模块,并且重新写入
/lib/modules/$(uname -r)/modules.dep 当中。若加入 -A 参数时,则 depmod
会去搜寻比 modules.dep 内还要新的模块,如果真找到新模块,才会升级。
-n :不写入 modules.dep ,而是将结果输出到萤幕上(standard out);
-e :显示出目前已加载的不可运行的模块名称
范例一:若我做好一个网络卡驱动程序,档名为 a.ko,该如何升级核心相依性?
[root@www ~]# cp a.ko /lib/modules/$(uname -r)/kernel/drivers/net
[root@www ~]# depmod
我们的 kernel 核心模块扩展名一定是 .ko 结尾的, 当你使用 depmod 之后,该程序会跑到模块标准放置目录 /lib/modules/$(uname -r)/kernel , 并依据相关目 录的定义将全部的模块捉出来分析,最终才将分析的结果写入 modules.dep 文件中
19.2.2 核心模块的观察
lsmod
使用 lsmod 之后,系统会显示出目前已经存在于核心当中的模块,显示的内容包括有:
-
模块名称(Module);
-
模块的大小(size);
-
此模块是否被其他模块所使用 (Used by)
[root@www ~]# modinfo [-adln] [module_name|filename]
选项与参数:
-a :仅列出作者名称;
-d :仅列出该 modules 的说明 (description);
-l :仅列出授权 (license);
-n :仅列出该模块的详细路径。
范例一:由上个表格当中,请列出 mii 这个模块的相关资讯:
[root@www ~]# modinfo mii
范例二:我有一个模块名称为 a.ko ,请问该模块的资讯为?
[root@www ~]# modinfo a.ko
19.2.3 核心模块的载入与移除
insmod 和 rmmod
modprobe 可以载入和移除模块
详细内容略
19.2.4 核心模块的额外参数设置:/etc/modprobe.d/*conf
重点就是要自己创建扩展名为 .conf 的文件,通过 options 来带入核心模块 参数啰!
19.3 Boot Loader: Grub2
略
19.4 开机过程的问题解决
19.4.1 忘记 root 密码的解决之道
略
19.4.2 直接开机就以 root 执行 bash 的方法
略
19.4.3 因文件系统错误而无法开机
略