Linux systemd启动守护进程,service启动顺序分析及调整service启动顺序

欢迎转载,请注明出处!

©MrWang_tju 2019.5.15

systemd是Liunx的启动守护进程,已被大多数Liunx发行版所采用。相较于之前被采用的init进程串行启动,systemd进程采用并行启动且为系统启动管理提供了成套的方案。

探索systemd启动的问题背景是,团队使用树莓派zero W+做的产品在系统启动后需要启动声卡播放音频文件,但声卡驱动相关的服务启动需要20s+,加上系统其余启动项耗费的时间,在45s左右才能实现音频播放。上电45秒系统不作出任何反应,用户难以忍受如此长的没有任何反馈的启动时间。

经过调整service启动顺序,最终实现上电22s播放音频文件。

树莓派烧录2019-04-08-raspbian-stretch-lite.img镜像,已经是极简化的系统,故没有通过内核裁剪实现加速启动(团队没有人有相关经验)。

声卡驱动来源:https://github.com/respeaker/seeed-voicecard.git

适用于驱动2mic、4mic、6mic树莓派喇叭模块

问题解决:

1.systemd相关基础知识,参考以下几篇博客  

http://www.ruanyifeng.com/blog/2016/03/systemd-tutorial-commands.html

https://www.jianshu.com/p/86adb6d5347b

2.分析当前系统各项服务启动时间及顺序

a.列出各项启动占用的时间,但由于是并行启动,启动时间不决定启动完成先后

systemd-analyze blame

 Linux systemd启动守护进程,service启动顺序分析及调整service启动顺序_第1张图片

b.列出启动矢量图,用浏览器打开boot.svg文件  得到各service启动顺序

systemd-analyze plot > boot.svg

 

Linux systemd启动守护进程,service启动顺序分析及调整service启动顺序_第2张图片

由svg矢量图得到声卡服务seeed-voicecard.service在17s左右开始启动,启动时间约20s,(和上电,外部计时时间不同,原因在于uboot引导、内存卡程序copy等时间未算在内)

分析seeed-voicecard.service

[Unit]
Description=Seeed Voicecard service
After=alsa-restore.service
 
[Service]
Type=oneshot
RemainAfterExit=yes
ExecStart=/usr/bin/seeed-voicecard
User=root
 
[Install]
WantedBy=sysinit.target

service将在alsa-restore.service之后启动,且属于sysinit.target组,目的在于执行seeed-voicecard 文件

systemd启动顺序约定为,当前服务满足启动条件,则立即创建进程进行并行启动。启动条件指服务的依赖关系(Requires、Wants)及顺序关键字(After、Before)等

c.列出seeed-voicecard.service的全部依赖关系,发现依赖关系异常多、且复杂。但service文件中并未提到如此多的依赖、怀疑依赖有继承关系,删掉After alsa-re... / 仍然有很多依赖。寻找何处定义依赖关系花费了很长时间,也是解决问题的关键。

systemctl list-dependencies seeed-voicecard.service

3.解决契机,发现keyboard启动服务很早被执行,观察keyboard service文件写法(路径 /lib/systemd/system),发现unit中包含

DefaultDependencies=no

 即systemd规定了许多默认依赖,一般的服务需要等待默认依赖的服务启动完毕后才可以启动。至此,问题解决大半。

剩余的问题在于,seeed-voicecard.service过早启动,(早于I2C、SPI等硬件初始化、早于boot.mont挂载点)导致程序启动失败。分析svg图,将seeed-voicecard.service置于如下几个服务之后,可确保较早启动且正常启动。

修改seeed-voicecard.service文件如下

[Unit]
Description=Seeed Voicecard service
DefaultDependencies=no
After=boot.mount
Before=nfs-config.service
Before=console-setup.service
Before=plymouth-read-write.service
Wants=DRStartSound.service

[Service]
Type=oneshot
RemainAfterExit=yes
ExecStart=/usr/bin/seeed-voicecard

[Install]
WantedBy=sysinit.target

此时分析boot启动svg图,发现seeed-voicecard.service启动时间提前至9s且启动时间缩短至8s以内,即17s即可播放音频文件。启动时间缩短的原因在于启动时刻提前,此时并行任务较少,声卡服务占用充足cpu资源,实现了快速启动。

学习探索systemd几天之后的总结:

1.依赖关系由默认依赖DefaultDependencies与service中定义的依赖组成,默认依赖确保了一般服务在内核启动完毕、硬件设备驱动启动完毕、内存管理等启动个完毕之后才启动服务。启动条件满足,服务会立刻被启动。

2.systemctl enable xxx.service命令实质是在target.wants文件中创建xxx.service的链接,同理disable实质在于断开链接。大多数的service文件存放于 /lib/systemd/system目录下。而创建的链接、按照不同target分属于不同的文件夹。seeed-voicecard.service被sysinit.target包含,创建的链接存在于 /etc/systemd/system/sysinit.target.wants文件夹中。

3.systemctl disable xxx.service命令有时不能移除创建的链接(或是在其他部分enable了该服务),服务仍然可以在其他进程、或下次上电时启动。要完全禁止某服务启动,应该用 systemctl mask xxx.service 要解除禁止,用systemctl unmask xxx.service

4.修改 /lib/systemd/system目录下的service,使用sudo systemctl daemon-reload更新链接中的service内容,或关机再次开机也会自动更新。

5.分析启动问题,有svg启动矢量图才能看清各项启动顺序及启动时间,实用且直观的表达方式

6.本次涉及的只有service相关内容,systemd的硬件启动device相关内容没有涉及到。

 

 

你可能感兴趣的:(Linux)