fangpsh's blog

使用Systemd 的Linux 的启动过程

这篇文章是回答知乎上一个朋友的问题:Systemd 的详细启动过程是怎样的
回答这个问题前需要了解一下计算机的启动过程和Linux 的启动过程,才能完整串起来。 关于计算机的启动,可以先阅读一下阮一峰的文章:计算机是如何启动的?,这篇文章在系统启动部分,大概提到了Linux 系统的启动, 不过不是十分详细,可以再看他的另一篇文章:Linux 的启动过程,文章所介绍的Init 程序是传统的Sysv。 而使用Systemd 的Linux 系统的差别就是在 Init 程序这一阶段。
在加载内核之前的阶段,这篇文章讲的挺细,可以顺便读一读:详解linux系统的启动过程及系统初始化

然后可以读一下这篇文章,对Systemd 的基础介绍,非常不错:浅析 Linux 初始化 init 系统,第 3 部分: Systemd,感觉IBM developerworks 的文章质量都挺不错的。

虚拟文件系统Initrd,启动到这一步之后,通过Switch-root 转到 Init 程序,即Systemd(也可以是Sysv 之类的),后面就是Systemd 如何启动服务进程的问题。
Initrd 这一步,Systemd 其实也可以接管,具体参考:initrd with systemd

在传统的Sysv 中,有Runlevel(启动级别)的概念,在Systemd 里面有Target 的概念,如下图:

runlevel

Systemd 有个单元文件(Unit)的概念,可以理解成一个单元文件就是一个服务单元,有很多类型的单元文件,Mount、Device、Service、Path、Timer 等,最常见的就是Service 单元:

例:/usr/lib/systemd/system/named.service,具体的解释请看官方文档:

[Unit]
Description=Berkeley Internet Name Domain (DNS)
Wants=nss-lookup.target
Wants=named-setup-rndc.service
Before=nss-lookup.target
After=network.target
After=named-setup-rndc.service

[Service]
Type=forking
EnvironmentFile=-/etc/sysconfig/named
Environment=KRB5_KTNAME=/etc/named.keytab
PIDFile=/run/named/named.pid

ExecStartPre=/usr/sbin/named-checkconf -z /etc/named.conf
ExecStart=/usr/sbin/named -u named $OPTIONS

ExecReload=/bin/sh -c '/usr/sbin/rndc reload > /dev/null 2>&1 || /bin/kill -HUP $MAINPID'

ExecStop=/bin/sh -c '/usr/sbin/rndc stop > /dev/null 2>&1 || /bin/kill -TERM $MAINPID'

PrivateTmp=true

[Install]
WantedBy=multi-user.target

Target 也是一种单元文件,但是它是引用和组织其他的单元文件,定义组织各种依赖关系。所以,Target 肯定可以实现Runlevel 的作用,只要定义六个Target 就可以了嘛。 再看看下面这张图,就大致明白了启动的时候是怎么加载服务进程的:

bootup

更多细节,以及关机的过程请参考:bootup