您的位置 首页 > 数码极客

【system32】干散货共享|系统技术原理实践(下)

关注独角兽吧,有更多的干货等着你!

Systemd文章续集出来了。上一期介绍了systemd的基本概念。本期详细说明了systemd相关的运营逻辑,希望对研究系统资源优化的优秀客户有帮助。

Systemd时代的引导过程

在systemd作为系统的init程序时代,Linux系统的启动过程可以大致分为六个阶段:BIOS自检阶段、GRUB引导阶段、内核加载阶段、Initrd虚拟根目录文件系统阶段、systemd初始化阶段和终端登录阶段。各阶段各司其职,为下一阶段的进行做铺垫,相互联系是不可缺少的。以下是对各个阶段的介绍。

1

BIOS自检阶段

从启动计算机开始,按下电源键打开计算机电源,系统开始加载主板内存中的第一条代码BIOS。系统进入BIOS自检阶段。

BIOS是基本输入/输出系统(全称基本输入输出系统),刻录到主板内存中。内容只能读取,如果更改,只能重新刻录到主板内存中。启动阶段,BIOS最重要的功能是开机自检。post逐个检查连接到主板的硬件设备(例如,CPU、主板、内存、软硬盘系统、键盘、光驱等某些主要硬件(例如,CPU、内存等)出现问题时),我们启动计算机时听到的滴声是BIOS蜂鸣器发出的声音。硬件有问题时蜂鸣器响2 ~ 3次,系统无法进行下一次引导。

BIOS检查所有硬件状态,如果状态正确,请根据设置的引导顺序找到相应的引导盘,然后将系统引导到相应的引导盘,继续引导系统。用过刷机的朋友应该知道,系统启动时按F12或delete键会进入BIOS界面,然后可以选择相应的启动盘进行擦洗。启动盘可以是安装盘、光驱、安装系统的光盘等。BIOS可以设置默认引导顺序。例如,可以将u盘设置为第一个引导项。启动时,BIOS启动系统,找到与USB驱动器对应的硬件接口。找不到USB时,BIOS将继续尝试第二个引导项目。选择引导项后,系统将进入相应的启动盘,开始执行启动盘第一个磁盘第一个扇区的代码。此BIOS自检阶段结束。

2

GRUB启动步骤

GRUB是GRand Unified Bootloader的缩写,是存储在第一个磁盘第一个扇区的主引导扇区中的多操作系统的管理员。如果计算机上安装了多个系统(如Linux和Windows系统),则可以通过GRUB移动光标以选择所需的系统。选择系统后,grub将根据系统分区表找到该系统所在的磁盘分区,加载相应的grub.cfg配置文件,通过配置文件加载/引导分区的文件系统驱动程序,然后在文件系统中找到系统内核,加载内核,引导,最后将系统控制传递给内核,从而结束GRUB引导阶段。

除了引导系统的主要功能外,GRUB还可以通过grub.cfg配置文件执行一些附加功能。Grub.cfg配置文件存储在/boot/grub/目录中。在配置文件中,Linux参数表示系统启动时加载的内核,可以配置为在系统中存储多个内核,或者在计算机上重新编译新内核时选择要加载的内核。Quiet参数类似于配置日志启动级别的loglevel参数。Splash参数用于配置其启动动画等。

3

内核内核加载步骤

在说明内核的开始之前,请先简要介绍一下Linux内核。Linux内核是在单个地址空间中运行的单个程序,它集中了系统的进程线程管理、内存管理、文件系统、驱动程序管理、网络管理等一些基本功能。内核中的每个函数都可以访问内核的其他部分,这与微内核(Windows系统)不同。

GRUB启动阶段结束后,内核接受系统控制后,初始化系统中各种设备(CPU、I/O设备、存储设备初始化等)的配置任务,然后内核创建内核状态的kernel_init进程,找到并解压缩initrd文件。完成与将驱动程序加载到Initrd虚拟根文件系统相关的硬件初始化,最后调用initrd虚拟根文件系统的init脚本。此时,内核在系统启动过程中的作用基本完成。内核等待initrd运行init进程,内核加载阶段结束。

4

Initrd虚拟根文件系统步骤

初始RAM磁盘(Initrd)是在GRUB阶段复制到内存并在内核中解压缩的虚拟根文件系统。解压缩后,目录结构类似于实际根文件系统,并包含驱动程序。下图是长颈鹿ini5的解压图

>

由于内核为了精简,只保留了最基本的模块,因此没有各种设备硬件的驱动程序,这些驱动程序就存放在了 initrd 里面,内核启动的时候,就从 initrd 中加载必要的驱动模块,完成硬件的初始化工作,接着,内核就开始执行虚拟根文件系统里的 init 程序,即虚拟根文件系统下的 systemd 程序,systemd 就作为内核的子程序,拿到了系统的控制权,开始做一些系统初始化方面的工作。

通过上面的描述,可以总结一下,虚拟根文件系统的阶段可以大致的分为:内核加载 initrd 里面的驱动程序、虚拟根文件系统下的 systemd 程序加载这两个过程,因此也可把虚拟根文件系统阶段分别归到内核加载阶段与 systemd 初始化阶段两个里面,是与上下两个阶段重合的一个阶段。此外,initrd 还提供了美化启动图形界面的功能,用来遮盖系统启动过程中的 log 日志输出,提升用户的体验。当 initrd 下的 systemd 进程完成环境的初始化,系统切换到真正的根文件系统的时候,initrd 阶段结束。


5

systemd 初始化阶段

systemd 是 system deamon 的简称,是一个 Linux 系统基础组件的集合,提供了系统与服务的管理,是 pid 为 1 的 init 进程,是所有进程的父进程。需要详细了解 systemd 进程的小伙伴可以阅读上一篇文章:systemd 介绍,这里重点讲解一下 systemd 开机过程中所做的事情。

通过前面的描述,我们可以把 systemd 分为两个阶段:虚拟根文件系统阶段与实根文件系统阶段。内核通过解压 initrd 文件得到虚拟根文件系统,然后执行虚拟根文件系统下的 init 程序来启动 systemd,systemd 作为内核的子进程在虚拟根文件系统下开始运行。虚拟根文件下的 systemd 首先对目前的系统进行一些检查,例如判断系统的运行状态是 user 态还是 system 态,系统是正常的启动状态还是异常出错后的重启状态等等,然后进行一些系统的初始化配置,包括:环境变量的配置、日志的相关配置等,接着对一些关键的文件系统进行挂载,主要包括 /proc、/sys、/dev、/var 这些基本的文件系统目录,到这一步后,systemd 就开始为切换实根文件目录做准备,保存一些已经配置的项目,并进行一些环境的适配之后,systemd 执行 setsid()系统调用脱离内核控制,成为一个完全独立的父进程,至此 systemd 的虚拟根文件系统阶段结束,systemd 进入到实根文件系统阶段。

在实根文件系统阶段,systemd 首先进行一些切换后的环境适配,然后开启日志终端的功能,并把系统启动时临时保存在内核中的日志提取出来,整理后存放到相应的日志文件中,下一步,systemd 开始进行一些系统能力的获取与系统相关的初始化与配置,例如:CPU 亲和力的获取、主机名的配置、系统 ID 的配置,cgroup 控制器的挂载、回环网络的配置等,完成以上的这些所有初始化工作后,systemd 作为 PID 为 1 的守护进程,开始了各个系统服务的创建与管理工作,根据相应 Unit 配置单元文件执行相应的系统服务,通过各个服务逐步完成系统的启动工作。systemd 执行 Unit 的顺序大致可以分为 ;ba;de,其中 与 ba 主要用来启动一些系统初始化相关的一些服务与执行一些开机启动早期的一些任务,de 则指向不同的“运行级别”target 文件,如果是进入命令行模式则指向 mul 文件,如果是进入图形界面模式则指向 gra 文件。至此,systemd 开机启动阶段的工作完成。


6

终端登录阶段

在完成了 systemd 初始化阶段以后,系统根据配置的运行级别,进入不同的登录界面,下面主要从图形登录界面进行介绍。在优麒麟操作系统中,systemd 之后的启动流程主要如下:systemd->lightdm->Xorg->lightdm-greeter->ukui-greeter->ukui-session,在优麒麟的终端通过 pstree 命令可以看到如下两个进程树:

lightdm 是一个全新的、轻量的 Linux 桌面的桌面显示管理器,它首先会拉起 Xorg,Xorg 是一个显示的后台,负责屏幕的绘制,然后 lightdm 还会拉起 lightdm-greeter,lightdm-greeter 是 lightdm 的子进程,它会拉起 ukui-greeter 进程,ukui-greeter 是登录界面进程,因此 ukui-greeter 起来以后,系统进入到登录界面,当输入登录的用户名与密码,用户名与密码效验通过以后,lightdm 建立个人的 ukui-session 桌面窗口管理器进程,至此,终端登录阶段结束,系统完成启动。



systemd 相关命令

systemd 提供了 systemctl 相关命令,用于管理系统,下面对一些基础常用命令进行介绍:

1 系统管理命令,控制系统电源状态

# 重启系统

$ sudo systemctl reboot

# 关闭系统,切断电源

$ sudo systemctl poweroff

# 暂停系统,使系统进入睡眠状态

$ sudo systemctl suspend

# 让系统进入冬眠状态

$ sudo systemctl hibernate

# 让系统进入交互式休眠状态

$ sudo systemctl hybrid-sleep

2 systemd-analyze 命令,用于查看启动耗时,可用来分析系统的启动效率

#查看启动耗时

$ systemd-analyze

#查看每个服务的启动耗时

$ systemd-analyze blame

#显示瀑布状的启动过程流

$ systemd-analyze critical-chain

#显示指定服务的启动流

$ systemd-analyze critical-chain a

3 hostnamectl 命令,用于查看当前主机的信息

#显示当前主机的信息

$ hostnamectl

#设置主机名

$ sudo hostnamectl set-hostname rhel7

4 Unit 相关命令,用来管理 Unit 配置单元

#列出正在运行的 Unit

$ systemctl list-units

#列出所有 Unit,包括没有找到配置文件的或者启动失败的

$ systemctl list-units --all

#列出所有没有运行的 Unit

$ systemctl list-units --all --state=inactive

#列出所有加载失败的 Unit

$ systemctl list-units --failed

#列出所有正在运行的、类型为 service 的 Unit

$ systemctl list-units --type=service

#立即启动一个服务

$ sudo systemctl start a

#立即停止一个服务

$ sudo systemctl stop a

#重启一个服务

$ sudo systemctl restart a

#杀死一个服务的所有子进程

$ sudo systemctl kill a

#重新加载一个服务的配置文件

$ sudo systemctl reload a

#重载所有修改过的配置文件

$ sudo systemctl daemon-reload

#显示某个 Unit 的所有底层参数

$ systemctl show

#显示某个 Unit 的指定属性的值

$ systemctl show -p CPUShares

#设置某个 Unit 的指定属性

$ sudo systemctl set-property CPUShares=500

5 日志管理,用来查看和过滤系统日志

#查看所有日志(默认情况下 ,只保存本次启动的日志)

$ sudo journalctl

#查看内核日志(不显示应用日志)

$ sudo journalctl -k

#查看系统本次启动的日志

$ sudo journalctl -b

$ sudo journalctl -b -0

#查看上一次启动的日志(需更改设置)

$ sudo journalctl -b -1

#查看指定时间的日志

$ sudo journalctl --since="2012-10-30 18:17: 16"

$ sudo journalctl --since "20 min ago"

$ sudo journalctl --since yesterday

$ sudo journalctl --since "2015-01-10" --until "2015-01-11 03:00"

$ sudo journalctl --since 09:00 --until "1 hour ago"

#显示尾部的最新 10 行日志

$ sudo journalctl -n

#显示尾部指定行数的日志

$ sudo journalctl -n 20

#实时滚动显示最新日志

$ sudo journalctl -f

#查看指定服务的日志

$ sudo journalctl /usr/lib/systemd/systemd

#查看指定进程的日志

$ sudo journalctl _PID=1

#查看某个路径的脚本的日志

$ sudo journalctl /usr/bin/bash

#查看指定用户的日志

$ sudo journalctl _UID=33 --since today

#查看某个 Unit 的日志

$ sudo journalctl -u nginx.service

$ sudo journalctl -u nginx.service --since today

#实时滚动显示某个 Unit 的最新日志

$ sudo journalctl -u nginx.service -f

#查看指定优先级(及其以上级别)的日志,共有8级

# 0: emerg

# 1: alert

# 2: crit

# 3: err

# 4: warning

# 5: notice

# 6: info

# 7: debug

$ sudo journalctl -p err -b

#日志默认分页输出,--no-pager 改为正常的标准输出

$ sudo journalctl --no-pager

#显示日志占据的硬盘空间

$ sudo journalctl --disk-usage

#指定日志文件占据的最大空间

$ sudo journalctl --vacuum-size=1G

#指定日志文件保存多久

$ sudo journalctl --vacuum-time=1years


END

关于 systemd 的完整介绍可以参考 systemd 官网手册:

以及 systemd 的官网中文翻译手册:

systemd 源码地址:


以上就是开机启动的过程中 systemd 的作用机制介绍,如果有什么建议,欢迎留言探讨哦~!

关于作者: luda

无忧经验小编鲁达,内容侵删请Email至wohenlihai#qq.com(#改为@)

热门推荐