干货分享 | Systemd 技术原理&实践(上)

本文介绍了Systemd作为Linux系统初始化程序的起源和发展,包括其从sysvinit到systemd的演进,以及systemd如何通过套接字激活实现服务并行启动,提高开机速度。此外,还探讨了systemd的主要功能,如cgroup进程管理,自动挂载,依赖关系管理和日志记录。Systemd采用Unit管理服务,通过提前创建套接字实现服务并行启动,减少了同步等待,提高了系统效率。

优麒麟的程序员小哥在研究如何优化系统资源模块时,查阅了许许多多的资料,发现没有一篇能详细把 systemd 的优势与原理说得很清楚的中文介绍文章,于是自己动手下载了 systemd 的源码,对照资料汇总了一份有关 systemd 的详解文章,希望能对研究 systemd 的优客有所帮助。

systemd 介绍

1

systemd 的起源

关于 systemd 的起源,首先要从 Linux 的 init 程序说起。Linux 系统在启动过程中,内核完成初始化以后,由内核第一个启动的程序便是 init 程序,路径为 /sbin/init(为一个软连接,链接到真实的 init 进程),其 PID 为1,它为系统里所有进程的“祖先”,Linux 中所有的进程都由 init 进程直接或间接进行创建并运行,init 进程以守护进程的方式存在,负责组织与运行系统的相关初始化工作,让系统进入定义好的运行模式,如命令行模式或图形界面模式。

init 程序的发展,大体上可分为三个阶段:sysvinit->upstart->systemd,根据 init 进程的发展特性,可以简单理解为如下:

sysvinit:init 系统通过 shell 脚本以串行的方式启动系统服务,下一个进程必须等待上一个进程启动完成后才能开始启动,因此系统启动的过程比较慢。

upstart:在 sysvinit 的基础上,把一些没有关联的程序并行启动,以提高启动的速度,但是存在依赖关系的程序仍然为串行启动。

systemd:通过套接字激活的机制,让所有无论有无依赖关系的程序全部并行启动,并且仅按照系统启动的需要启动相应的服务,最大化提高开机启动速度。

目前优麒麟操作系统使用的就为 systemd。systemd 的意思为 system daemon,意为系统守护进程,由 Lennart Poettering 带头开发,采用更加优秀的服务框架,并且与老的 sysvinit 兼容,其设计目的就是克服 sysvinit 与 upstart 的缺点,进一步地提高启动速度。目前主流的系统中,systemd 的守护进程主要分为系统态(system)与用户态(user),可以在 ps -ef 中看到 systemd 的守护进程,如下:

PID 为1的进程/sbin/init 即是 system 态的 systemd,它为一个软链接,指向真实的 systemd 路径,在优麒麟操作系统中一般放在/lib/systemd/目录:

systemd 为进程服务集合的总称,它包含许多的进程,负责控制、管理系统的资源,其中包括 systemd-login,负责用户登录相关信息的创建、修改与删除;systemd-sleep 控制系统的休眠、睡眠状态切换等等。在优麒麟操作系统下,它们主要集中在/lib/systemd/文件目录:

<think>我们正在讨论systemd的原理。根据用户提供的引用材料,特别是引用[2]中提到的“systemd 时代的开机启动流程”和引用[3]中提供的多个资源(包括IBM的分析文章和鸟哥的Linux私房菜),我们可以系统地解释systemd的工作原理。 systemd的原理可以从以下几个方面进行阐述: 1. **设计目标**:为了解决传统SysVinit的启动速度慢、脚本复杂、依赖管理弱等问题,systemd的设计目标包括提高启动速度(并行启动服务)、简化服务管理、提供强大的依赖关系管理。 2. **架构核心**:systemd采用基于单元(unit)的架构,每个单元代表一个系统资源(服务、套接字、挂载点等)。单元之间通过依赖关系构成有向无环图(DAG),从而实现并行启动。 3. **关键技术**: - **套接字激活(Socket Activation)**:服务在第一次被请求时才启动,减少系统启动时的负担。 - **总线激活(D-Bus Activation)**:类似于套接字激活,适用于D-Bus服务。 - **利用Linux内核特性**:如cgroups(用于进程跟踪和资源控制)、namespaces(用于容器隔离)等。 4. **启动流程**: - 内核加载并启动systemd(作为PID=1的进程) - systemd解析默认目标(target),通常是`graphical.target`或`multi-user.target` - 根据目标单元的依赖关系,并行启动所有依赖单元 - 在启动过程中,处理套接字激活、文件系统挂载、定时器等 5. **依赖管理**:systemd通过单元文件中的`[Unit]`节定义依赖关系,如: - `Requires`:强依赖,如果依赖单元启动失败,当前单元也会失败 - `Wants`:弱依赖,即使依赖单元失败也不影响当前单元 - `After`:定义启动顺序 6. **事件驱动**:systemd采用事件驱动机制,当某个单元的状态发生变化(如激活、失败)时,会触发依赖它的单元的动作。 现在,我们将按照用户要求的格式,使用LaTeX公式(例如描述依赖关系图)、代码块(示例单元文件)来组织回答,并生成相关问题。 注意:数学公式主要用于表达依赖关系图(使用图论符号)或资源管理(如cgroups的权重分配)。 </think>### Systemd 工作原理详解 SystemdLinux 系统的核心初始化系统和服务管理器,其设计原理围绕**并行化**、**依赖驱动**和**事件触发**三大核心思想。以下是其关键原理: #### 1. **单元依赖图(Unit Dependency Graph)** Systemd 将所有系统资源抽象为**单元**(服务、挂载点、套接字等),通过依赖关系构建有向无环图(DAG): $$ \text{目标单元} \rightarrow \text{服务单元} \rightarrow \text{依赖单元} $$ - **依赖类型**: - `Requires`(强依赖):依赖单元失败则当前单元失败 - `Wants`(弱依赖):依赖单元失败不影响当前单元 - `After`/`Before`(时序控制) ```ini # 示例:Nginx 服务依赖网络(network.target) [Unit] Description=Nginx Web Server After=network.target # 网络就绪后才启动 Requires=network.target ``` #### 2. **Socket-Based 按需激活** 通过套接字监听实现服务延迟启动: 1. 创建 `/run/nginx.sock` 套接字单元 2. 客户端连接套接字时触发 `nginx.service` 启动 3. 服务处理请求后自动休眠(节省资源) ```bash $ systemctl status nginx.socket # 查看套接字激活状态 ``` #### 3. **并行启动机制** 通过依赖图分析实现最大并行度: 1. 拓扑排序所有单元 2. 识别无依赖的单元立即启动 3. 动态解决依赖冲突(如互斥服务) > 相比传统 SysVinit 串行启动,速度提升 30-50%[^2] #### 4. **资源隔离与控制组(cgroups)** 所有进程纳入 cgroups 层级管理: - **资源限制**:CPU/内存配额 - **进程跟踪**:精确管理服务树 - **沙箱隔离**:`PrivateTmp=true` 隔离临时目录 ```bash $ systemd-cgls # 查看 cgroups 层级 ``` #### 5. **事务性操作** 关键操作具备原子性: - 启动服务前预检查依赖 - 失败时自动回滚到安全状态 - 通过日志快照(Journal)记录操作序列 ```bash $ journalctl --list-boots # 查看启动日志序列 ``` #### 6. **目标(Target)协调系统状态** 类似 SysVinit 的运行级别,但支持动态切换: | 目标 | 作用 | |---------------|------------------------| | `graphical.target` | 图形界面模式 | | `multi-user.target`| 多用户命令行模式 | | `emergency.target` | 紧急恢复模式 | --- ###
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值