ブログ

Armadillo-X1,Armadillo-IoT G3/G3L: USBメモリが接続された時のイベントを検知する方法

at_keita.mogaki
2018年1月18日 18時11分

はじめに

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)