一、开机流程
Linux系统组成
- kernel 实现进程管理、内存管理、网络管理、驱动程序、文件系统、安全功能等功能
- rootfs 包括程序和 glibc 库
- 程序:二进制执行文件
- 库:函数集合, function, 调用接口(头文件负责描述)
开机流程
- BIOS 开机自检,并依据设定获取第一个启动设备。
- 读取第一个启动设备 MBR 的 Boot Loader(引导加载程序,如 Grub2)。
- 依据 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 需要的服务
概念解释
BIOS
Basic Input Output System。它是一组固化到计算机主板上的一个ROM(只读存储器)芯片上的程序,它保存着计算机最重要的基本输入输出的程序、开机后自检程序和系统自启动程序,它可从CMOS中读写系统设置的具体信息。
无论传统的BIOS还是新的UEFI BIOS统称为BIOS。其主要功能是为计算机提供最底层的、最直接的硬件设置和控制。
MBR
Master Boot Record。主引导记录,是一些代码和数据,位于硬盘的第一个扇区(扇区共512字节)。无论传统的MBR或新的GPT,都有MBR区块。
深入理解
- 主引导记录:即MBR,-共446字节。可以安装开机管理程序。
- 分区表:即partition table,共64字节。记录着硬盘的分区信息。
- 结束标志:2个字节
需要根据具体情况判断其到底是指整个主引导扇区,还是主引导扇区的前446字节。
简单理解:MBR表示磁盘最前面可安装boot loader的区块。
如果MBR损坏,可能会导致计算机无法启动或无法正确识别硬盘上的分区。
Boot Loader
引导加载程序 或 开机管理程序。位于MBR。
目前主流的boot loader 是grub2。
安装位置
- MBR
- 每个分区的boot sector
三个阶段
- 1st stage:执行Grub主程序。Grub安装在MBR。由于MBR太小,所以与配置文件分开放
- 1.5 stage:识别不同的文件系统
- 2nd stage:加载Grub配置文件 /boot/grub2/grub.cfg。配置文件在文件系统中。
主要功能
- 提供选单:用户可选择不同的开机选项,即多重引导
- 加载内核:读取内核文件并执行
- 转交其它loader:将开机功能转交给其它loader负责
多重操作系统
问
操作系统必须使用自己的loader才能加载属于自己操作系统的核心,但MBR只有一个,如何在一台主机安装Windows与Linux系统?
答
一、Windows使用 NTLDR 引导,而Linux使用 Grub2 引导。
二、每个文件系统(或称为分区)都会各自保留一块启动扇区(boot sector)提供操作系统安装 boot loader,而通常操作系统默认都会安装一份 loader 到其根目录所在的文件系统的boot sector。对于Linux,可选择将boot loader安装到MBR,也可选择不安装至MBR,若选择安装到MBR,那么MBR和boot sector都会存在一份boot loader程序;对于Windows,预设会主动将MBR与boot sector都装上一份boot loader,所以可能会存在MBR被不同操作系统的boot loader覆盖的问题。
三、Linux的Grub2具有控制转交的功能;但Windows的NTLDR预设不具有控制转交功能。即不能使用Windows的loader加载Linux的loade,但可使用Linux的loader来加载Windows的loader。
综述,避免MBR被没有转移功能的Windows loader覆盖,所以要先装Windows再装Linux。
图示:
选单一:MBR(grub2) -->kernel file --> booting
选单二:MBR(grub2) -->boot sector(Windows loader) --> Windows kernel --> booting
选单三:MBR(grub2) --> boot sector(grub2) -->kernel file --> booting
Grub2
Grub2是linux主流的boot loader程序。
配置文件
/boot/grub2/grub.cfg
磁盘与分区在Grub2中的代号
(hd0,1) | 默认语法,由grub2自动判断分区格式 |
(hd0,msdos1) | 此磁盘分区为MBR模式 |
(hd0,gpt1) | 此磁盘分区为gpt模式 |
注意:磁盘编号从0开始,分区编号从1开始
- 第一个搜索到的硬盘代号为:(hd0)
- 该硬盘的第一个分区代号为:(hd0,1)
规律参考
第一个硬盘的第一个逻辑分区代号为 (hd0,msdos5)。
旧版grub的磁盘编号和分区编号都是从0开始。
配置文件的维护
修改 /etc/default/grub文件 与 /etc/grub.d/ 目录内容。不要修改 /boot/grub2/grub.cfg
/etc/default/grub
[root@wenzi ~]# cat /etc/default/grub
GRUB_TIMEOUT=5 预设倒数读秒的秒数
GRUB_DISTRIBUTOR="$(sed 's, release .*$,,g' /etc/system-release)"
GRUB_DEFAULT=saved saved表示默认启动的系统是用户最后选择的那个系统
GRUB_DISABLE_SUBMENU=true 是否隐藏次级选单,一般都隐藏
GRUB_TERMINAL_OUTPUT="console" 数据输出终端的格式,默认是文字
GRUB_CMDLINE_LINUX="crashkernel=auto rhgb quiet" 定义了 GRUB 在启动 Linux 内核时传递的参数。这里的参数是 "crashkernel=auto"(在系统崩溃时自动启用内核)、"rhgb"(在图形模式下显示 Red Hat Graphics Boot)、"quiet"(安静模式,不显示详细的启动信息)
GRUB_DISABLE_RECOVERY="true" 禁用救援模式
修改此文件,设置倒数读秒为10秒,使用 grub2-mkconfig 重新生成 /etc/grub2/grub.cfg
[root@wenzi ~]# cat /etc/default/grub
GRUB_TIMEOUT=10
GRUB_DISTRIBUTOR="$(sed 's, release .*$,,g' /etc/system-release)"
GRUB_DEFAULT=saved
GRUB_DISABLE_SUBMENU=true
GRUB_TERMINAL_OUTPUT="console"
GRUB_CMDLINE_LINUX="crashkernel=auto rhgb quiet"
GRUB_DISABLE_RECOVERY="true"
使用 grub2-mkconfig 重新生成grub.cfg文件。-o 指定生成的文件路径
[root@wenzi ~]# grub2-mkconfig -o /boot/grub2/grub.cfg
Generating grub configuration file ...
Found linux image: /boot/vmlinuz-3.10.0-1160.el7.x86_64
Found initrd image: /boot/initramfs-3.10.0-1160.el7.x86_64.img
Found linux image: /boot/vmlinuz-0-rescue-bdec72d022c54c9a974631ed16b60939
Found initrd image: /boot/initramfs-0-rescue-bdec72d022c54c9a974631ed16b60939.img
done
查看实际配置文件已修改
[root@wenzi ~]# cat /boot/grub2/grub.cfg | grep timeout
if [ x$feature_timeout_style = xy ] ; then
set timeout_style=menu
set timeout=10
# Fallback normal timeout code in case the timeout_style feature is
set timeout=10
/etc/grub.d/ 目录
使用 grub2-mkconfig 生成 grub.cfg 文件时,grub2工具会分析/etc/grub.d/ 目录里的文件。
[root@wenzi ~]# ls /etc/grub.d/
00_header 00_tuned 01_users 10_linux 20_linux_xen 20_ppc_terminfo 30_os-prober 40_custom 41_custom README
00_header
:此文件包含GRUB的默认设置和命令,它在GRUB引导加载器的所有阶段都会被读取。00_tuned
:此文件包含根据系统配置的优化设置,这些设置可能会覆盖默认设置。01_users
:此文件允许你定义在GRUB引导加载器中使用的用户。10_linux
和20_linux_xen
:这些文件包含用于GRUB引导加载器的Linux和Xen内核的配置。它们会根据在/etc/default/grub
文件中定义的菜单项顺序进行加载。20_ppc_terminfo
:这个文件包含PowerPC (PPC) 体系架构的终端信息数据库。这可以帮助GRUB在引导过程中对系统进行适当的设置。30_os-prober
:此文件用于探测并添加其他操作系统到GRUB的菜单中。40_custom
和41_custom
:这些文件允许你添加自定义的配置,它们会在所有其他配置之后加载。
示例:
/etc/grub2.cfg 中选单内容
grub2-install
用于安装GRUB2引导加载器的工具。它用于将GRUB2配置文件和相关文件安装到正确的位置,以便在计算机启动时能够正确加载并引导操作系统。
grub2-install [--boot-directory=DIR] INSTALL_DEVICE
- --boot-directory=DIR:指定grub2安装目录。grub2-install 默认会将grub2所有文件复制到 /boot/grub2/ 下。
- INSTALL_DEVICE:安装GRUB2的设备或者分区,例如 /dev/sda1
将GRUB2安装到 /dev/sda1 分区,并且所有的文件都将会被复制到 /boot/gragon/ 目录下
grub2-install --boot-directory=/boot/gragon/ /dev/sda1
Kernel
操作系统的核心。可实现进程管理、内存管理、网络管理、驱动程序、文件系统、安全功能等功能。
核心文件位置
/boot 目录,以 vmlinuz 开头的文件,如 vmlinuz-3.10.0-1160.el7.x86_64
/boot 目录
config-3.10.0-1160.el7.x86_64 Linux内核的配置文件,其中包含了内核的配置选项和参数
grub 已过时,无需理会
grub2 引导加载程序的相关目录。它们包含了引导加载程序所需的文件和配置。
initramfs-0-rescue-bdec72d022c54c9a974631ed16b60939.img 用来救援的虚拟文件系统
initramfs-3.10.0-1160.el7.x86_64.img 正常开机用的虚拟文件系统
initramfs-3.10.0-1160.el7.x86_64kdump.img 内核出问题用的虚拟文件系统
lost+found 当ext文件系统出错时会把遗失的片段放置在此。使用xfs文件系统的话,没有此目录
symvers-3.10.0-1160.el7.x86_64.gz 内核符号版本文件,用于调试和排错
System.map-3.10.0-1160.el7.x86_64 系统映射文件,用于内核调试和排错
vmlinuz-0-rescue-bdec72d022c54c9a974631ed16b60939 救援用的内核文件
vmlinuz-3.10.0-1160.el7.x86_64 内核文件,最重要
/boot/initramfs
虚拟文件系统。可通过boot loader加载到内存中,被解压缩为一个虚拟的根目录,且提供一个加载开机过程需要的内核模块的可执行程序。载入完成后核心呼叫systemd继续后续的开机流程。
若要重建 initramfs,可使用 dracut 命令。
Systemd
Linux最新的初始化系统,PID为1。Centos6是init。
主要功能是准备软件的执行环境,如主机名,网络设定,语言,文件系统格式,一些服务的启动。所有的动作通过 /etc/systemd/system/default.target 规划。
新式target和旧式runlevel对应关系
[root@wenzi ~]# ll /usr/lib/systemd/system/runlevel*
usr/lib/systemd/system/runlevel0.target -> poweroff.target
/usr/lib/systemd/system/runlevel1.target -> rescue.target
/usr/lib/systemd/system/runlevel2.target -> multi-user.target
/usr/lib/systemd/system/runlevel3.target -> multi-user.target
/usr/lib/systemd/system/runlevel4.target -> multi-user.target
/usr/lib/systemd/system/runlevel5.target -> graphical.target
/usr/lib/systemd/system/runlevel6.target -> reboot.target
systemd处理流程
以centos7为例,查看graphical.target依赖哪些服务
[root@wenzi ~]# systemctl list-dependencies graphical.target
graphical.target
● ├─display-manager.service
● ├─network.service
● ├─systemd-update-utmp-runlevel.service
● └─multi-user.target
● ├─auditd.service
● ├─crond.service
● ├─dbus.service
● ├─irqbalance.service
● ├─kdump.service
● ├─network.service
● ├─NetworkManager.service
● ├─plymouth-quit-wait.service
● ├─plymouth-quit.service
● ├─postfix.service
● ├─rhel-configure.service
● ├─rsyslog.service
● ├─sshd.service
● ├─systemd-ask-password-wall.path
● ├─systemd-logind.service
● ├─systemd-readahead-collect.service
● ├─systemd-readahead-replay.service
● ├─systemd-update-utmp-runlevel.service
● ├─systemd-user-sessions.service
● ├─tuned.service
● ├─vmtoolsd.service
● ├─basic.target
● │ ├─microcode.service
● │ ├─rhel-dmesg.service
● │ ├─selinux-policy-migrate-local-changes@targeted.service
● │ ├─paths.target
● │ ├─slices.target
● │ │ ├─-.slice
● │ │ └─system.slice
● │ ├─sockets.target
● │ │ ├─dbus.socket
● │ │ ├─systemd-initctl.socket
● │ │ ├─systemd-journald.socket
● │ │ ├─systemd-shutdownd.socket
● │ │ ├─systemd-udevd-control.socket
● │ │ └─systemd-udevd-kernel.socket
● │ ├─sysinit.target
● │ │ ├─dev-hugepages.mount
● │ │ ├─dev-mqueue.mount
● │ │ ├─kmod-static-nodes.service
● │ │ ├─plymouth-read-write.service
● │ │ ├─plymouth-start.service
● │ │ ├─proc-sys-fs-binfmt_misc.automount
● │ │ ├─rhel-autorelabel-mark.service
● │ │ ├─rhel-autorelabel.service
● │ │ ├─rhel-domainname.service
● │ │ ├─rhel-import-state.service
● │ │ ├─rhel-loadmodules.service
● │ │ ├─sys-fs-fuse-connections.mount
● │ │ ├─sys-kernel-config.mount
● │ │ ├─sys-kernel-debug.mount
● │ │ ├─systemd-ask-password-console.path
● │ │ ├─systemd-binfmt.service
● │ │ ├─systemd-firstboot.service
● │ │ ├─systemd-hwdb-update.service
● │ │ ├─systemd-journal-catalog-update.service
● │ │ ├─systemd-journal-flush.service
● │ │ ├─systemd-journald.service
● │ │ ├─systemd-machine-id-commit.service
● │ │ ├─systemd-modules-load.service
● │ │ ├─systemd-random-seed.service
● │ │ ├─systemd-sysctl.service
● │ │ ├─systemd-tmpfiles-setup-dev.service
● │ │ ├─systemd-tmpfiles-setup.service
● │ │ ├─systemd-udev-trigger.service
● │ │ ├─systemd-udevd.service
● │ │ ├─systemd-update-done.service
● │ │ ├─systemd-update-utmp.service
● │ │ ├─systemd-vconsole-setup.service
● │ │ ├─cryptsetup.target
● │ │ ├─local-fs.target
● │ │ │ ├─-.mount
● │ │ │ ├─boot.mount
● │ │ │ ├─rhel-readonly.service
● │ │ │ └─systemd-remount-fs.service
● │ │ └─swap.target
● │ │ └─dev-disk-by\x2duuid-999dc4a1\x2d79e7\x2d480a\x2dabf5\x2da79a594ed019.swap
● │ └─timers.target
● │ └─systemd-tmpfiles-clean.timer
● ├─getty.target
● │ └─getty@tty1.service
● └─remote-fs.target
由上可知,流程大致如下:
- local-fs.target + swap.target:这两个target主要在挂载本机/etelfstab里面所规范的文件系统与相关的内存交换空间。
- sysinit.target:这个target主要在侦测硬件,加载所需要的核心模块等动作。初始化系统
- basic.target:加载主要的外围硬件驱动程序与防火墙相关任务。准备系统
- multi-user.target下的其它一般系统或网络服务的加载
- graphical.target图形界面相关服务的加载
相容systemV的rc-local.service
centos6,将某些程序或脚本设置为开机自启,可将其绝对路径写到 /etc/rc.d/rc.local 文件中。
centos7,要使用centos6的方法,除去上述步骤外,还要检查 /etc/rc.d/rc.local 是否具有可执行权限。
rc-local.service 此服务无需启动,会自己判断 /etc/rc.d/rc.local 是否具有可执行权限从而决定是否启动自己
centos7默认是未启动的
查看权限
[root@wenzi ~]# ll /etc/rc.d/rc.local
-rw-r--r--. 1 root root 473 Oct 2 2020 /etc/rc.d/rc.local
查看服务状态
[root@wenzi ~]# systemctl status rc-local.service
● rc-local.service - /etc/rc.d/rc.local Compatibility
Loaded: loaded (/usr/lib/systemd/system/rc-local.service; static; vendor preset: disabled)
Active: inactive (dead)
查看是否挂在 multi-user.target ,可见没有查询出结果
[root@wenzi ~]# systemctl list-dependencies multi-user.target | grep rc-local
此时赋予 /etc/rc.d/rc.local 可执行权限
[root@wenzi ~]# chmod a+x /etc/rc.d/rc.local
[root@wenzi ~]# ll /etc/rc.d/rc.local
-rwxr-xr-x. 1 root root 473 Oct 2 2020 /etc/rc.d/rc.local
[root@wenzi ~]# systemctl daemon-reload
[root@wenzi ~]# systemctl list-dependencies multi-user.target | grep rc-local
● ├─rc-local.service
yum安装httpd,手动设置开机自启
[root@wenzi ~]# yum -y install httpd
[root@wenzi ~]# cat /etc/rc.d/rc.local
#!/bin/bash
touch /var/lock/subsys/local
/usr/sbin/apachectl start
[root@wenzi ~]# systemctl daemon-reload
重启系统,观察httpd是否开启自启
[root@wenzi ~]# systemctl status httpd
● httpd.service - The Apache HTTP Server
Loaded: loaded (/usr/lib/systemd/system/httpd.service; enabled; vendor preset: disabled)
Active: active (running) since Sat 2023-10-28 14:34:15 CST; 1min 29s ago
发现 rc-local.service 也自动启动了
[root@wenzi ~]# systemctl status rc-local.service
● rc-local.service - /etc/rc.d/rc.local Compatibility
Loaded: loaded (/usr/lib/systemd/system/rc-local.service; static; vendor preset: disabled)
Active: active (exited) since Sat 2023-10-28 14:34:15 CST; 7min ago
Process: 781 ExecStart=/etc/rc.d/rc.local start (code=exited, status=0/SUCCESS)
可知,已实现开机自启
二、核心与核心模块
核心一般是压缩文件,具有模块化功能。核心模块拓展名以 .ko 结尾
存放位置
核心:/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/ (要安装才会有,预设不安装)
核心模块与相依性
核心模块位于 /lib/modules/$(uname -r)/kernel
[root@wenzi ~]# uname -r
3.10.0-1160.el7.x86_64
[root@wenzi ~]# ls /lib/modules/3.10.0-1160.el7.x86_64/kernel/
arch crypto drivers fs kernel lib mm net sound virt
- arch:与硬件平台有关的项目,主要指的是CPU的类别,例如x86、x86_64、Xen虚拟支持等。
- crypto:核心所支持的加密技术,例如md5或者是des等。
- drivers:一些硬件的驱动程序,例如显卡、网络卡、PCI相关硬件等。
- fs:核心所支持的文件系统,例如vfat、reiserfs、nfs等。
- kernel:内核,是操作系统的核心部分,负责管理系统的资源。
- lib:库文件,包含一些函数和数据,供程序在运行时使用。
- mm:内存管理,负责分配和管理系统内存。
- net:网络相关的组件,包括网络协议的实现和网络设备的驱动等。
- sound:声音相关的组件,包括音频设备的驱动和音频信号的处理等。
- virt:虚拟化相关的组件,包括虚拟化技术的支持和虚拟化管理等。
depmod
使用depmod命令生成 modules.dep 文件,此文件记录核心支持的各个模块的相依性。
此文件默认位于 /usr/lib/modules/3.10.0-1160.el7.x86_64/modules.dep
观察核心模块
lsmod
显示目前核心已加载的模块。
内容格式:模块名称 模块大小 此模块是否被其它模块使用
[root@wenzi ~]# lsmod
Module Size Used by
binfmt_misc 17468 1
snd_seq_midi 13565 0
snd_seq_midi_event 14597 1 snd_seq_midi
vmw_vsock_vmci_transport 30577 1
vsock 36367 2 vmw_vsock_vmci_transport
ext4 584133 1
...
modinfo
显示内核模块相关信息
[root@wenzi ~]# modinfo xfs
filename: /lib/modules/3.10.0-1160.el7.x86_64/kernel/fs/xfs/xfs.ko.xz
license: GPL
description: SGI XFS with ACLs, security attributes, no debug enabled
author: Silicon Graphics, Inc.
alias: fs-xfs
retpoline: Y
rhelversion: 7.9
srcversion: ACB9CF86C248DD09DC2B428
depends: libcrc32c
intree: Y
vermagic: 3.10.0-1160.el7.x86_64 SMP mod_unload modversions
signer: CentOS Linux kernel signing key
sig_key: E1:FD:B0:E2:A7:E8:61:A1:D1:CA:80:A2:3D:CF:0D:BA:3A:A4:AD:F5
sig_hashalgo: sha256
核心模块的加载和移除
modprobe
modprobe [-cfr] 模块名称
-c:列出目前系统所有的模块
-f:强制加载该模块
-r:移除某个模块
-l:显示可用的模块
-t:指定模块类型
加载vfat模块、移除vfat模块
[root@wenzi ~]# modprobe vfat
[root@wenzi ~]# modprobe -r vfat