はじめに
「FPGA+SoC+Linux+Device Tree Overlay+FPGA Manager(ブートイメージの提供)」@Qiitaで FPGA+SoC の Linux Kernel と Debian8 rootfs を提供した記事を書きましたが、その際初めて systemd に触れて、デバイスドライバを起動時に自動的にロードしたり、停止時に自動的に取り外したい時に、ちょっと躓いたのでその覚え書き。
systemd は Debian では Debian8(jessie) から採用されたシステム管理システムです(ややこしい)。
主にこちらの記事が参考になりました。というより、ほぼそのまんま。
service ファイルの記述例
dtbocfg (Device Tree Blob Overlay Configuration File System)の例を以下に挙げます。
[Unit]
Description=Device Tree Overlay Service.
After=udev.target
After=dbus.target
After=avahi.target
After=syslog.target
[Service]
Type=oneshot
RemainAfterExit=yes
ExecStart=/sbin/modprobe dtbocfg
ExecStop=/sbin/rmmod dtbocfg
[Install]
WantedBy=multi-user.target
ポイントは [Service] の Type=oneshot と RemainAfterExit=yes です。
特に RemainAfterExit=yes を指定しないと、サービスをスタートさせてデバイスドライバをロード(modprobe dtbocfg)した後、すぐに停止してデバイスドライバは取り外し(rmmod dtbocfg)てしまいます。
もともと systemd の ExecStart で指定するコマンドやスクリプトは実行するとそのままシステムに常駐することを想定しているようです。しかし、modprobe はデバイスドライバをロードしたらすぐに終了して戻ってきてしまうので、RemainAfterExit=yes を指定しないと systemd はサービスが終わったものと認識してすぐに ExecStop を実行します。
もうひとつおまけに fpgacfg (FPGA Configuration Interface for Linux FPGA Manager Framework) の例。
[Unit]
Description=FPGA Manager Service.
After=device-tree-overlay.service
[Service]
Type=oneshot
RemainAfterExit=yes
ExecStart=/sbin/modprobe fpgacfg
ExecStartPost=/usr/bin/fpgacfg-service.rb --install
ExecStop=/sbin/rmmod fpgacfg
ExecStopPost=/usr/bin/fpgacfg-service.rb --remove
[Install]
WantedBy=multi-user.target
fpgacfg は Device Tree Overlay を使うので、[Unit] の After=device-tree-overlay.service で device-tree-overlay.service を先に起動しておくようにします。
また、fpgacfg は device-tree に記された Low Level FPGA Driver と接続/切断する必要があります。fpgacfg はそのための専用のスクリプト(fpgacfg-service.rb)を用意しています。ExecStartPost でデバイスドライバのロード直後に "/usr/bin/fpgacfg-service.rb --install" を実行し、ExecStopPost でデバイスドライバの取り外し直後に "/usr/bin/fpgacfg-service.rb --remove" を実行するようにしています。
service を systemd に登録
上記の service ファイルを /etc/systemd/system にコピーします。
service を Linux 起動時に自動的に起動する
システムが起動してから次のようにコマンドを叩けば、次の Linux 起動時に自動的に service も起動します。
shell$ sudo systemctl enable device-tree-overlay.service
Created symlink from /etc/systemd/system/multi-user.target.wants/device-tree-overlay.service to /etc/systemd/system/device-tree-overlay.service.
shell$ sudo systemctl enable fpga-manager.service
Created symlink from /etc/systemd/system/multi-user.target.wants/fpga-manager.service to /etc/systemd/system/fpga-manager.service.