FPs

Systemd 基础介绍

Systemd 这个系列文章是大三时在某游戏公司实习整理的文档,按照内容做了下整理,拆分为几篇文章发出来,内容比较杂乱粗浅,如果能对他人有些帮助也是极好的了。

前言

systemd 是 Linux 下的一种 init 软件,由 Lennart Poettering 带头开发,并 在 LGPL 2.1 及其后续版本许可证下开源发布。其开发目标是提供更优秀的 框架以表示系统服务间的依赖关系,并依此实现系统初始化时服务的并行启 动,同时达到降低 Shell 的系统开销的效果,最终代替现在常用的 System V 与 BSD 风格 init 程序。  
init(为英语:initialization 的简写)是 Unix 和类 Unix 系统中用来产生其 它所有进程的程序。它以守护进程的方式存在,其进程号为 1。  

关于 init 的基础介绍请阅读 wikipedia [init 条目](https://en.wikipedia.org/wiki/Init)

Systemd 由于众多出色的特性以及良好的兼容性已经被各大发行版采用作为默认 init 程序,例如 openSUSE(12.1+)、Fedora(15+)、ArchLinux(2012-10-13+)等。 Debian 技术委员会经过投票 (The Debian technical committee vote concludes) 之 后决定 Debian 的下一个版本 Debian8(别名:jessie)中以 Linux 为内核的版本将转 换到 systemd。之后,基于 Debian 的下游发行版 Ubuntu 也宣布将切换到 systemd。 所以 systemd 将是下一代的 init 程序,有必要在 debian 8 发布之前对其进行详细的 调研。

本文是以 debian 8 为调研平台,systemd 为调研目标整理撰写而成,除去前言部 分外,包含以下部分:

  • 基础介绍
    • systemd 基础介绍,systemd 相关基础概念与特性的介绍等。
  • 启动分析
    • 分析 Linux 启动过程中 systmed 启动部分。
  • 详细介绍
    • 对 systemd 在系统管理、进程管理、设备管理、日志管理等等方面进行分点 详细介绍。
  • 附录
    • debian7-8 目前已知的更新与变化。
    • 通用初始化脚本的更新。
    • 其他升级注意事项

注 1: 本文摘录和引用了大量其他资料,由于时间与人力限制未能一一注明来源。 如要切实深入的了解 systemd 某一部分的内容,建议您认真阅读对应章节后的参考链 接所指向的内容。

注 2:本文整理撰写以及进行 systemd 的相关实验时,debian 8 还未冻结,实验 平台为 debian testing 分支,systemd 版本为 208,所以部分内容日后看来准确性可 能会有所偏差。

注 3:章节前带 [!] 符号的表示此节为较重要的内容。

基础介绍

Systemd Components

关于 Systemd 的基础介绍,强烈建议阅读 IBM DeveloperWorks 的《浅析 Linux 初始化 init 系统,第 3 部分: Systemd》一文,这篇文章通俗和全面的介绍了 Systemd 的主要特性以及与 Systemd 相关的概念。
关于 Systemd 的基础使用建议阅读 Arch Wiki 的《Systemd》 这一条目,阅读完 之后将对 Systemd 的基本管理与操作有个基础性的了解。
请您务必在完整阅读完以上两篇文章之后再阅读本文后续内容。

启动分析

通过上文的基础介绍之后,您应该对 Systemd 有一个基础性的了解,本节将介绍 Linux(with systemd) 的启动过程中与 Systemd 相关的部分,希望您在阅读本节之后可 以对 Systemd 的工作原理与流程有一个全局的概念。

Linux(with systemd) 启动过程

  1. BIOS
    • POST
    • Boot Sequence
  2. MBR
  3. Boot loader
    • e.g. Grub
  4. Kernel
    • initrd
  5. Systemd
  6. ...

本文将主要介绍在第 4 步骤向第 5 步骤过渡的过程以及第 5 步骤之后的过程。

Kernel -> Systemd

Kernel 将完成系统与硬件的检测与驱动初始化,在以 rw 的方式挂载根文件系 统 (switch root)。Kernel 需要通过虚拟的文件系统 –initrd 向用户空间的 /sbin/ init 过渡。

关于 initrd

"Initrd ramdisk 或者 initrd 是指一个临时文件系统,它在启动阶段被 Linux 内核调用。initrd 主要用于当 “根” 文件系统被挂载之前,进行准备工作" -- Wikipedia

更多介绍: wikipedia: initrd, Linux2.6 内核的 Initrd 机制解析

重点关注 initrd 如何向 systemd 进行转移。手动解压后查看 init 脚本内容 (注:debian 目前使用的是 cpio 格式的 initrd)。

由上图可知内核加载成功之后,首先运行的是 /sbin/init 程序。

而 /sbin/init 实际上是 /lib/systemd/sytemd 的软链接,即 switch root 之后其实直接开始运行 systemd 程序:

接下来将介绍启动任务交接给 systemd 的后续情况。

Systemd bootup process

/sbin/init(systemd) 是第一个运行的程序,它的进程编号 PID=1,其他所有的 进程都是从它衍生,都是它的子进程。

服务进程树:

Target (Not Just Runlevel)

要了解 systemd 的启动过程,需要先了解 systemd 中相对于以往旧的 init 软件新 引入的 target。

启动级别(runlevel)是一个旧的概念。现在,systemd 引入了一个和启动 级别功能相似又不同的概念 ——目标(target)。不像数字表示的启动级别, 每个目标都有名字和独特的功能,
并且能同时启用多个。一些目标继承其他 目标的服务,并启动新服务。systemd 提供了一些模仿 sysvinit 启动级别 的目标,仍可以使用旧的 telinit 启动级别命令切换。
—Archlinux Wiki

它们本身实际上并不做什么,只是引用其他 unit(unit 是 systemd 的配置 单元,包含.service,.mount,.scokets 等)而已。这样便可以对 unit 做一个 统一的控制。(例如:multi-user.target 相当于在传统使用 SysV 的系统中运 行级别 5);bluetooth.target 只有在蓝牙适配器可用的情况下才调用与蓝牙 相关的服务,如:bluetooth 守护进程、obex 守护进程等)

更多介绍:

对于常见的 runlevel:0,1,2,3,4,5,6,systemd 都有对应的 target 与之 对应,不同的 target 与不同的服务相关,启动时候进入默认的 target,即可带起下属 的服务。
-Fedora Wiki

由上图可知每个 SvsV 的启动级别与之对于的 Systemd target,另 外 systemd 一般还会有一个默认的 target(default.target),这个 target 是上表中的 某一个 target 的软链接,表示默认的启动级别,等同于 /etc/inittab 文件中的 initdefault 值。

相对于/etc/rc[0~6].d,Systemd 采用target 来管理不同的服务,同时也是对服务进行抽象和分层管理的一种方式。除了以上表中的target ,还有不同的target。例如graphical.target 依赖着multi-user.target, multi-user.target 依赖着basic.target,
basic.target 依赖着 sysinit.target...具体 target 的依赖关系后文分析。
看一个例子,即可明白这种关系:

basic.target requires sysinit.targe
basic.target wants sockets.target、timer.target、paths.targt

系统包含以下常见 target:

Bootup

当systemd 启动系统时, 它首先会激活 default.target, 从而激活其下属依赖 的服务。下图体现了常见的启动逻辑:

  • local-fs-pre.target: 本地设备挂载之前执行的 target,用于执行挂载前的任务。
  • local-fs.target: 在执行这个此 target 之前会执行systemd-fstab-generator, 将 /etc/fstab 转换为 systemd 的 unit。本 target 主要执行磁盘挂载、扫描等任务。
  • swap.target: 挂载交换分区。
  • cryptsetup.target: 执行磁盘加密任务。
  • sysinit.target: 包含 early boot 的所有任务。
  • timers.target:timers 是 systemd 中类似 cron 的单元,此 target 配置所有 timer 任务。
  • paths.target:path 是 systemd 中使用 inotify API 的单元,监视目录或文件的变更而触发任务,此 target 配置所有 path 任务。
  • sockets.target: 配置所有 socket 单元。
  • resue.target: 触发系统恢复服务。
  • basic.target: 包含启动的基础单元。
  • emergency.target: 触发急救模式的任务。
  • multi-user.target: 配置多用户模式。
  • graphical.target: 执行登录的图形界面任务。
  • 更完整的 target 介绍: systemd.special

另外在 systemd 中还有.wants 这个文件夹,一个 target 可能需要若干服务,需将 这些服务 ln -s 到与这个 target 同名的.wants 文件夹中:

例如我们写了一个 ABC.service, 在文件中指明了依赖的服务和启动先后顺序,只 需要将 ABC.targt ln -s 到合适的.wants 文件中即可。

Bootup in the Initial RAM Disk (initrd)

本节参考自: Bootup in the Initial RAM Disk (initrd)(具体细节待补充, 现阶段 debian 未采用这种方式)。

在上文中我们提到在 initrd 阶段,init 脚本启动了 /sbin/init(systemd),而 实际上在 initrd 中可以直接启用 systemd。
initrd 中默认的 target 将是 initrd.target, 系统启动直到 bacsic.target 之前的过程都与上文的类似,从这点之后 systemd 激活 了一个特殊的 initrd.target。
如果根设备可以挂在到/sysroot,sysroot.mout 单元将被 激活,到达 initd-root-fs.tatrget。之后 initrd-parse-etc.service 将扫描 /sysroot/etc/ fstab,为了找到/usr 的挂载点。
所有找到的项目将会被挂在到/sysroot 之下,到达 initrd-fs.target 。initrd-cleanup.service 独立与 initrd-switch-root.target 运行。
最后 一步,initrd-switch-root.service 被激活,系统 switch root 到 /sysroot。

The initrd Interface of systemd

关机过程

关机的过程同样也是激活某些相关的 target,完成磁盘的卸载、进程的退出等等清 理工程,见图 shutdown。

本节参考链接

2016-03-16 Systemd