Ubuntu Weekly Recipe

第555回 いま,あらためてudev

この記事を読むのに必要な時間:およそ 7 分

皆さん,ホットプラグってますか!? 猫も杓子もUSB端子なこのご時世,いろんなデバイスをPCに繋いだり取り外したりしていることと思います。そこで今回はデバイスの自動認識やデバイス名の設定など,システムの裏方として大活躍しているudevの基本を紹介します。

動的デバイス管理ツールudev

udevとはsystemdの別名です。

すみません,言い過ぎました。Ubuntuで使われているudevは,systemdの一部として提供されるデバイスの認識に関わるデーモンでありツールです。もともとは独立したソフトウェアでしたが,2012年にsystemdと同じソースツリーから提供されるようになりました。ただしデーモンプロセスとしてはsystemd(PID=1)から独立しています※1)⁠

※1
systemdの本業である「initシステム」とudevが担うデバイスの認識は,特にシステム起動時やホットプラグ動作時は相補的な作業となります。たとえばデバイスを検知することで特定のサービスを起動する場合など,より密に連携するためにコードをマージすることになったようです。ただし「udevは欲しいけどsystemdは使わない」といったユースケースもあります。一応,udev単体でもビルドできることになっていますが,Gentooなどはudevをeudevとしてフォークしているようです。また,組み込み系で使われているYoctoもudevをインストールしようとするとまずeudevが使われます。

udevは具体的には次のような流れでデバイスを認識し,設定された作業を行います。

  • カーネルが追加・削除されたデバイスを認識する
  • ueventによってudevに変更内容が通知される
  • udevは通知された内容をもとに事前に設定されたルールに従って処理する

たとえばPCIやUSB,I2Cなどのデバイスバスのドライバーは,バスに何かが接続されたらACPIやDevice Treeといった事前に設定されたデバイス情報や,接続されたデバイスに汎用的にアクセスできるベンダー名・デバイス名などから通知する情報をとりまとめます。udevはその情報を元に必要に応じてカーネルモジュールをロードし,そのモジュールなどのドライバーからさらにデバイス固有の情報が通知されます。

udev自身がルールに従って主体的に情報を収集し,後続のルールに通知することもあります。そのようなルールの流れを経て,udevやそこから呼び出されるツールたちは次のような機能を実現するのです。

  • 適切なモジュールの自動ロード
  • ストレージ接続・切断時のマウント・アンマウント
  • 各種デバイスファイルの権限の変更
  • デバイス認識に伴うスクリプトの実行
  • デバイスファイルやシンボリックリンクの作成
  • サービスの起動・停止

特に任意のファイル名やシンボリックリンクの作成は,デバイスの認識順に依存しない「永続的なデバイス名」の命名に役立っています。

udevのルールと変更方法

udevがインストールされたシステムにおいて,ユーザー側にもっとも影響するのが「ルールファイル」です。ルールファイルの記述方法を把握しておくと,任意のデバイスを接続したときの挙動をコントロールできます。

udevのルールファイルは以下のいずれかのディレクトリに保存されています。

  • /etc/udev/rules.d:システムの管理者が作成・変更することを想定したルールファイルの保存場所
  • /run/udev/rules.d:一時的に作成されるルールファイルの保存場所
  • /lib/udev/rules.d:パッケージ等システムが提供するルールファイルの保存場所

上記ディレクトリのうち「.rules」を拡張子として持つファイルのみをルールファイルとして扱います。

複数のディレクトリで同じファイル名だった場合は,⁠/etc,/run,/lib」の順で優先されます。つまり「/lib」以下の任意のルールファイルを無効化したい場合,⁠/etc」以下に同名のファイルを「/dev/null」へのシンボリックリンクにすれば良いのです※2)⁠

※2
もちろん拡張子を「.rules」以外に変えるという方法もありますが,⁠/lib」以下のファイルはパッケージのアップデートによって復活する可能性があるので注意が必要です。

モジュール自動ロードのルールファイル

具体的なルールファイルの中身を見てみましょう。⁠/lib/udev/rules.d/80-drivers.rules」は必要なカーネルモジュールをロードする,udevが提供するルールファイルです。

# do not edit this file, it will be overwritten on update

ACTION!="add", GOTO="drivers_end"

ENV{MODALIAS}=="?*", RUN{builtin}+="kmod load $env{MODALIAS}"
SUBSYSTEM=="tifm", ENV{TIFM_CARD_TYPE}=="SD", RUN{builtin}+="kmod load tifm_sd"
SUBSYSTEM=="tifm", ENV{TIFM_CARD_TYPE}=="MS", RUN{builtin}+="kmod load tifm_ms"
SUBSYSTEM=="memstick", RUN{builtin}+="kmod load ms_block mspro_block"
SUBSYSTEM=="i2o", RUN{builtin}+="kmod load i2o_block"
SUBSYSTEM=="module", KERNEL=="parport_pc", RUN{builtin}+="kmod load ppdev"
KERNEL=="mtd*ro", ENV{MTD_FTL}=="smartmedia", RUN{builtin}+="kmod load sm_ftl"

LABEL="drivers_end"

ルールファイルはキーバリューの変数をベースにした判定システムです。変数にはカーネルからueventと渡されるものだけでなく,前のルールで設定された値もあります。また「#」で始まる行や空行は無視されます。

変数には「マッチングに使える変数」「値を代入できる変数」の2種類が存在します。マッチング変数の判定をカンマで連結することで,すべてにマッチする場合のみ,変数に値が代入されます。変数によっては代入された値によって特定の処理を実行します。

ルールは1行ずつ処理されていきます。上記ファイルの内容を順番に見ていきましょう。

著者プロフィール

柴田充也(しばたみつや)

Ubuntu Japanese Team Member株式会社 創夢所属。数年前にLaunchpad上でStellariumの翻訳をしたことがきっかけで,Ubuntuの翻訳にも関わるようになりました。