作者:酸葡萄洗澡她_606 | 来源:互联网 | 2023-07-14 15:26
第十九章启动流程、模块管理与Loader19.1Linux的启动流程分析19.1.1启动流程一览加载BIOS的硬件信息与进行自我检测,并根据设置取得第一个可启动
第十九章 启动流程、模块管理与Loader
19.1 Linux的启动流程分析
19.1.1 启动流程一览
- 加载BIOS的硬件信息与进行自我检测,并根据设置取得第一个可启动的设备;
- 读取并执行第一个启动设备内的MBR的启动引导程序(就是grub2、spfdisk等程序);
- 根据启动引导程序的设置加载kernel,kernel会开始检测硬件与加载驱动程序;
- 在硬件驱动成功后,kernel会主动调用systemd程序,并以default.target流程启动。
其中第4步包括:
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加载
loader最主要的功能是:识别操作系统的文件格式,并据以家在内核到内存中去执行。
之前好奇的一个问题:安装双系统的时候,都是先按照Windows,在安装Linux,原因如下:
- 在Linux系统安装的时候,你可以选择将boot loader安装到MBR,也可以选择不安装;如果选择安装到MBR的话,那么理论上你在MBR和boot sector都会有一份boot loader的程序;
- 在Windows系统安装的时候,会默认主动地将MBR与boot sector都装上一份boot loader。
- Windows的loader默认不具有控制权转交的功能,因此你不能使用Windows的loader来加载Linux的loader。
内核文件一般会被放置到/boot
里,取名为/boot/vmlinuz
。
虚拟文件系统存在的意义:
虚拟文件系统的特色是,他也能够通过boot loader来加载到内存中,然后这个文件会被解压缩并且在内存中模拟成一个根目录,且此模拟在内存中的文件系统能够提供一个可执行的程序,通过该程序来加载启动过程中所最需要的内核模块,通常这些模块就是USB、RAID、LVM、SCSI等文件系统与磁盘接口的驱动程序。等加载完成后,会帮助内核重新调用systemd来开始后续的正常启动流程。
19.1.3 第一个程序systemd及使用default.target进入启动程序分析
在内核加载完毕,进行完硬件检测与驱动程序加载后,此时你的主机硬件应该已经准备就绪了(ready)。此时内核会主动地调用第一个程序,就是systemd。
systemd的主要功能就是准备软件执行的环境,包括系统的主机名、网络设置、语言设置、文件系统格式及其他服务的启动等。所有操作都会通过systemd的默认启动服务集合(/etc/systemd/system/default.target
)来规划的。
了解系统服务的启动流程:
systemctl list-dependencies graphical.target
CentOS 7.x 的启动流程:
- local-fs.target、swap.target:用于挂载本机/etc/fstab里面所规范的文件系统和相关的内存交换分区;
- sysinit.target:检测硬件,加载所需要的内核模块等操作;
- basic.target:加载主要的外围硬件驱动程序与防火墙相关任务;
- multi-user.target:其他一般系统或网络服务的加载;
- 图形界面相关服务,如gdm.service等其他服务的加载。
19.1.4 systemd执行sysinit.target初始化系统、basic.target准备系统
sysinit.target初始化系统:基本的内核功能、文件系统、文件系统设备的驱动,都在这个时刻处理完毕。
basic.target准备系统:加载音效驱动程序、防火墙、CPU微指令功能、启动与设置SELinux的安全上下文、将启动过程信息写入/var/log/dmesg中、加载管理员指定的模块、加载timer功能等,就是一个最普通的操作系统。
chmod a+x /etc/rc.d/rc.local 赋予这个文件执行权限
这样,很多脚本就可以放在/etc/rc.d/rc.local这个文件内,系统每次启动都会去执行这个文件内的命令,简单易用。
19.1.5 systemd启动mult-user.target下的服务
系统默认的服务启动脚本设置:/usr/lib/systemd/system
;
管理员自己开发与设置的脚本设置:/etc/systemd/system
。
19.1.6 systemd启动graphical.target下面的服务
如果default.target是multi-user.target的话,这一步不会执行。
让用户可以登录的服务是gdm.service。
systemctl isolate multi-user.target 从图形化界面模式切换到命令行模式
systemctl isolate graphical.target 从命令行模式切换到图形化界面模式
19.1.7 启动过程会用到的主要配置文件
关于模块的配置文件:/etc/modprobe.d/*.conf
(单纯要内核加载模块的位置)和/etc/modules-load.d/*.conf
(可以加上模块参数的位置);
常见的环境配置文件:/etc/sysconfig/*
。其中:
- authconfig:规范用户的身份认证的功能;
- cpupower:主要是Linux内核如何操作CPU的原则;启动后系统会让CPU以最大性能的方式运行,不启动就是用多少算多少;
- Firewalld、iptables-config、ebtables-config:与防火墙服务的启动外带的参数有关(在服务器篇讲解);
- network-scripts/:主要用在设置网卡方面。
19.2 内核与内核模块
从19.1可知,在整个启动的过程中,是否能够成功地驱动我们主机的硬件设备是内核的工作,而内核一般都是压缩文件,因此在使用内核前,就得先将它解压缩后,才能加载到内存中。
目前内核都是具有可读取模块化驱动程序的功能,就是所谓的模块化的功能。模块化就像个插件,这个插件可以由硬件开发厂商提供,也可能内核本来就支持,一般较新的硬件通常需要硬件开发商提供驱动程序模块。
内核与内核模块的位置:
- 内核:
/boot/vmlinuz
或/boot/vmliuz-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 与硬件平台有关- crypto 内核支持的加密技术- drivers 硬件驱动程序,显卡、网卡、PCI相关硬件等- fs 文件系统,如vfat、reiserfs、nfs等- lib 函数库- net 与网络有关的各项协议数据,还有防火墙模块等- sound 与音效有关的各项模块
内核支持的模块的各项依赖性,可以通过检查/lib/modules/$(uname -r)/modules.dep
这个文件来获取。
depmod [-Ane]不加任何参数时,depmod会主动分析目前内核的模块,并重新写入modules.dep这个文件中。-A 若加入-A参数,depmod会去查找比modules.dep新的模块,真的找到新模块,才会更新-n 不写入modules.dep,只将结果显示到屏幕-e 显示出目前已加载的不可执行的模块名称
若做好了一个网卡驱动程序a.ko
(内核模块的扩展名一定是.ko
),该如何更新内核依赖性:
cp a.ko /lib/modules/$(uname -r)/kernel/drivers/net
depmod
19.2.2 查看内核模块
想知道自己的内核目前加载了多少模块:
lsmod
想知道某个模块是啥:
modinfo [-adln] [module name | filename]如:
modinfo drm
modinfo a.ko
19.2.3 内核模块的加载与删除
自行手动加载模块:
modprobe [-cfr] module_name-c 列出所有模块-f 强制加载该模块-r 删除某个模块modprobe vfat
modprobe是直接去查找modules.dep的记录,可以解决模块的依赖性问题,而且还不需要知道该模块的详细路径,很方便。
使用modprobe加载cifs模块,查看该模块的相关模块是哪个:
modprobe cifs
lsmod | grep cifs
modprobe -r cifs 测试完后删除该模块
19.2.4 内核模块的额外参数设置:/etc/modprobe.d/*.conf
如果某些特殊的需求导致你必须要让内核模块加上某些参数时,重点要自己建立扩展名为.conf的文件,通过options来带入内核模块参数。
19.3 Boot Loader:Grub2
boot loader 是加载内核的重要工具,没有它,内核也就没有办法被系统加载。
现阶段Linux中最主流的boot loader是grub2。
19.3.1 boot loader的两个stage
stage1:执行boot loader程序。因为MBR太小了,所以MBR或启动扇区通常仅安装boot loader的最小主程序,并没有安装loader的相关配置文件。
stage2:主程序加载配置文件。通过boot loader加载所有的配置文件,以及相关的环境参数文件。配置文件一般放在/boot下。
19.3.2 grub2的配置文件/boot/grub2/grub.cfg
初探
这一节之难难于上青天,使人阅后凋朱颜。
19.3.3 grub2配置文件维护/etc/default/grub
和/etc/grub.d
/etc/default/grub
:是主要的环境配置文件,包括倒数时间设置、是否隐藏选项、信息输出的终端模式、默认启动选项、内核的外加参数。
/etc/grub.d
:选项创建的脚本。00_head、10_linux、30_os-prober、40_custom(我们所能修改的)。
40_custom文件内容也大多在放置管理员自己想要加进来的选项项目,menuentry就是一个选项。menuentry的功能如下:
- 直接指定内核启动
- 通过chainloader的方式移交loader的控制权
19.4 启动过程的问题解决
19.4.1 忘记root密码的解决之道
只要能进入并且挂载,然后重新设置一下root的密码,就能挽回。
通过rd.break
的内核参数来设置。
19.4.2 直接启动就以root执行bash的方法
不如上一节通过rd.break
的内核参数来设置的方法靠谱。
19.4.3 因文件系统错误而无法启动
最容易出错的设置导致无法顺利启动的步骤,通常是/etc/fstab
这个文件,尤其是用户在时间磁盘配额、LVM、RAID时,最容易写错参数,有没有经过mount -a来测试挂载,就立刻重新启动。