はじめに
Armadillo-X1,Armadillo-IoT G3/G3L(以降Armadilloと記載)で、USBメモリが接続された時のイベントを検知する方法を紹介します。
Linuxではデバイスの状態変化があった時、カーネルからイベント通知(uevent)が送信されます。USBメモリが接続された時のイベントを検知するには、このueventを取得する方法が一般的です。今回は例として、Armadilloに接続したUSBメモリのデバイス名が、udevのrulesファイルに設定したデバイス名と一致した時に、USBメモリデバイスを/mntにマウントさせます。
USBメモリのデバイス名を取得する方法
まず、ArmadilloにUSBメモリを接続してください。接続完了後、lsコマンドを用いてUSBメモリのデバイス名を確認します。
root@armadillo:~# ls /dev/sd[a-z]
/dev/sda
root@armadillo:~#
lsコマンドの実行結果より、USBメモリのデバイス名がsdaであることがわかります。
udevのrulesファイルを作成する
udevのrulesファイルを作成します。これは、udevdに送信されたueventに対して、対象のUSBデバイスの識別方法等を記述するものです。
rulesファイルを作成します。
root@armadillo:~# vi /etc/udev/rules.d/10-device-connect-test.rules
rulesファイルは、先程取得したデバイス名を元に以下のように記述して下さい。
ACTION=="add", \
SUBSYSTEMS=="usb", \
KERNEL=="sda", \
RUN:="/etc/udev/device-connect-test.sh"
rulesファイルに記載された各キーの役割について、以下に説明を記載します。
・ACTION:イベントを発生させたアクションの名前を照合します。今回はUSBメモリ接続時にアプリを実行するためaddを設定します。
・SUBSYSTEMS:一致するデバイスサブシステム名を検索します。今回はUSBメモリのデバイスサブシステム名であるusbを設定します。
・KERNEL:イベントによって影響を受けるデバイス名を照合します。今回は先程取得したsdaを設定します。
・RUN:実行するコマンドを設定します。今回は後述する/etc/udev/device-connect-test.shの実行を設定します。
追加したrulesファイルを適応させます。
root@armadillo:~# udevadm control --reload
実行するシェルスクリプトの作成
USBメモリが接続された時に、実行するテストアプリを作成します。今回は以下のシェルスクリプトで試します。
このシェルスクリプトは、USBメモリデバイスが接続された際にmountを行う単純な処理となります。
root@armadillo:~# vi /etc/udev/device-connect-test.sh
シェルスクリプトは以下のように実装します。
#!/bin/bash
mount /dev/sd[a-z][0-9] /mnt
作成したシェルスクリプトに実行権限を与えます。
root@armadillo:~# chmod +x /etc/udev/device-connect-test.sh
systemd-udevd.service 設定変更
使用しているLinuxのバージョンが「Linux-4.9: Debian GNU/Linux 9 (stretch) 」である場合、systemd-udevd.serviceの設定を変更する必要があります。
以下のようにMountFlags=slaveをMountFlags=sharedに変更してください。
root@armadillo:~# vi /lib/systemd/system/systemd-udevd.service
# This file is part of systemd.
#
# systemd is free software; you can redistribute it and/or modify it
# under the terms of the GNU Lesser General Public License as published by
# the Free Software Foundation; either version 2.1 of the License, or
# (at your option) any later version.
[Unit]
Description=udev Kernel Device Manager
Documentation=man:systemd-udevd.service(8) man:udev(7)
DefaultDependencies=no
Wants=systemd-udevd-control.socket systemd-udevd-kernel.socket
After=systemd-udevd-control.socket systemd-udevd-kernel.socket systemd-sysusers.service
Before=sysinit.target
ConditionPathIsReadWrite=/sys
[Service]
Type=notify
OOMScoreAdjust=-1000
Sockets=systemd-udevd-control.socket systemd-udevd-kernel.socket
Restart=always
RestartSec=0
ExecStart=/lib/systemd/systemd-udevd
KillMode=mixed
WatchdogSec=3min
TasksMax=infinity
MountFlags=shared
MemoryDenyWriteExecute=yes
RestrictRealtime=yes
RestrictAddressFamilies=AF_UNIX AF_NETLINK AF_INET AF_INET6
設定変更後、systemd-udevd.serviceの再起動を行います。
root@armadillo:~# systemctl restart systemd-udevd
詳細は以下のmanページをご確認ください。
・systemd.exec manページ
http://man7.org/linux/man-pages/man5/systemd.exec.5.html
・mount manページ
http://man7.org/linux/man-pages/man2/mount.2.html
動作確認
USBメモリをArmadilloに接続して下さい。USBメモリ接続後、/tmpにUSBメモリがmountされていることを確認して下さい。
root@armadillo:~# mount | grep sda
/dev/sda1 on /mnt type vfat (rw,relatime,fmask=0022,dmask=0022,codepage=437,iocharset=iso8859-1,shortname=mixed,errors=remount-ro)