udev
udev (user /dev) は systemd の Linux カーネルのためのデバイスマネージャです。/dev 内のデバイスノードを管理し、デバイスを追加または削除するときのユーザ空間での操作のすべてを取り扱います。
sys-apps/systemd-utils パッケージに含まれる udev は、OpenRC init システムを使用する Gentoo システムのためのデフォルトのデバイスマネージャとして、systemd から独立して利用されます。
udev とは何ですか?
/dev ディレクトリー
多くの Linux ユーザは、/dev/sda1 はカーネルが認識した最初のディスクの最初のパーティションを指す最短の手段だということを知っています。これはとても平易でしょう。
しかし、USB や IEEE 1394、ホットスワップ可能な PCI などのホットプラグ対応デバイスを考えてみてください。最初のデバイスというのはこれらのうちどれのことでしょう? そして、いつまで最初のデバイスといえるのでしょう? 最初のデバイスが消えたとき、他のデバイスは何と名付けられるのでしょうか? それは進行中の処理に影響するでしょうか? 誰かが(たまたま最初のプリンターになっていた)レーザープリンターのプラグを引っこ抜いたというだけの理由で、印刷ジョブが高性能なレーザープリンターからほとんど壊れかけのマトリックスプリンターに突然移ってしまったとしたら、笑ってしまいませんか?
デバイスマネージャに入ってみましょう。今どきのデバイスマネージャならば必ず:
- ユーザスペースで動作します。
- 動的にデバイスファイルが生成されたり削除されたりします。
- 一貫したデバイス命名を行います。
- ユーザスペースのアプリケーション・プログラム・インターフェイス (API) を提供します。
デバイスの構造に変化が生じるたびにカーネルは uevent を発行し、デバイスマネージャがそれを受け取ります。それから、デバイスマネージャは /etc/udev/rules.d 、 /run/udev/rules.d および /lib/udev/rules.d ディレクトリで定義されたルールに従います。uevent 内に含まれている情報を元に実行する必要があるルール(群)を探し必要なアクションを行います。これらのアクションにはデバイスファイルの作成・削除も含まれており、また特定のファームウェアファイルのカーネルメモリへの読み込みも実行します。
インストール
udev を更新するときは、システムがブート不可に陥らないようにするための情報を得るために、udev アップグレードガイドを確認してください。
カーネル
udev には、以下のカーネルオプションが必要です:
General setup ---> [*] Configure standard kernel features (expert users) ---> [ ] Enable deprecated sysfs features to support old userspace tools [*] Enable signalfd() system call Enable the block layer ---> [*] Block layer SG support v4 Networking support ---> Networking options ---> <*> Unix domain sockets Device Drivers ---> Generic Driver Options ---> () path to uevent helper [*] Maintain a devtmpfs filesystem to mount at /dev < > ATA/ATAPI/MFM/RLL support (DEPRECATED) ---> File systems ---> [*] Inotify support for userspace Pseudo filesystems ---> [*] /proc file system support [*] sysfs file system support
USE フラグ
Portage は udev USE フラグを、他のパッケージの udev サポートを有効化するものであると認識しています。この USE フラグ値を USE フラグリストに追加すると (すべての Linux プロファイルでデフォルトです)、virtual/udev パッケージを自動でインストールするでしょう:
/etc/portage/make.confUSE="udev"
USE flags for sys-apps/systemd-utils Utilities split out from systemd for OpenRC users
+acl
Add support for Access Control Lists
+kmod
Enable kernel module loading via sys-apps/kmod
+sysctl
Install systemd-sysctl and sysctl.d files
+tmpfiles
Enable systemd-tmpfiles
+udev
Enable systemd-udev (userspace device manager)
boot
Enable systemd-boot (UEFI boot manager)
kernel-install
Enable kernel-install
secureboot
Automatically sign efi executables using user specified key
selinux
!!internal use only!! Security Enhanced Linux support, this must be set by the selinux profile or breakage will occur
split-usr
Enable behavior to support maintaining /bin, /lib*, /sbin and /usr/sbin separately from /usr/bin and /usr/lib*
sysusers
Enable systemd-sysusers
test
Enable dependencies and/or preparations necessary to run tests (usually controlled by FEATURES=test but can be toggled independently)
ukify
Enable systemd-ukify
Emerge
USE フラグを設定したら、システムを更新して変更を反映させましょう:
root #emerge --ask --changed-use --deep @world設定
サービス
起動時に udev を開始するには、sysinit ランレベルに追加してください。これは root 権限で以下のコマンドを実行することで行えます:
root #rc-update add udev sysinit
root #rc-update add udev-trigger sysinit
高度な設定
ルール
udev は、uevent (カーネルによって送信されるイベント) から抽出された値と、発見されたデバイスのプロパティに対してマッチする、ルールの集合を提供します。マッチングルールは、デバイスノードを命名して作成し、デバイスのセットアップおよび構成のために設定されたプログラムを実行することができます。
ルール定義は以下の 2 箇所に保存されます:
- /lib/udev/rules.d/ - このディレクトリ内のルールは 特定のパッケージによりインストールされ、一般にユーザが変更すべきではありません;
- /etc/udev/rules.d/ - このフォルダはエンドユーザ固有のルールのためのものです。新しいルールはすべてこのディレクトリに追加すべきです;
これらのディレクトリ内で、複数のルールファイル (接尾辞 .rules を持つもの) が英数字順に走査されます。ルールファイルの中では udev は、uevent にマッチする式、マッチする状態 (その uevent がデバイスが追加または削除されたことによるものか)、および実行するコマンドの組み合わせを探します。
イベントマッチングは、次のような情報に基づいています:
- uevent の SUBSYSTEM (uevent がどのタイプのデバイスに対して発生したか);
- 対処される ACTION (追加 (add)、変更 (change)、または削除 (remove));
- 1 個または複数の属性 (ATTR または ATTRS)。デバイスクラス、ベンダー、またはその他のデバイス情報など;
- カーネルが提供する名前 (KERNEL)。sd* (SCSI/SATA ディスクに対して) または input* (マウスやキーボードなどの入力デバイスに対して) など;
- 1 個または複数の環境設定 (ENV)。複数のルールに渡って情報を送信するために使用されます。
この情報に基づいて、ルールは以下のことを宣言することができます:
- 一部の情報を後々のイベントと共有する必要があるか (環境変数を利用して)
- /dev 内にリンクを作成する必要があるか
- コマンドを実行する必要があるか
Udev はこれをすべてのマッチするルールに対して (最初のマッチ後に止まることなく) 実行し、柔軟なデバイス管理のアプローチを可能にしています。
永続的なデバイス名
カーネルは非同期的にデバイスを検出し、udev はカーネルの sysfs ファイルシステムをミラーリングするため、デバイスは検出された順に番号が振られて名前が付けられます。そのためデフォルトでは udev は永続的なデバイス名を提供しません。しかしながら一部のデバイスクラスでは、これらを提供するための機構があります:
- ストレージデバイスに関しては、udev はデバイスの ID、ラベル、UUID、およびパスに基づいて、追加のシンボリックリンクを作成します。/dev/disk/by-* ディレクトリを参照してください。そのため、例えば /dev/sda などのデバイスファイルを使用する代わりに、ファイル /dev/disk/by-label/SOME_LABEL を使用することができます。
- 入力デバイスに関しては、/dev/input ディレクトリ内で同様のことが行われます。
- カスタムルールを使用することで、ユーザは自身のデバイスファイルを作成することができるようになります。
予測可能なネットワークインターフェースの命名
新しいネットワークインターフェース命名規約は以前のものとは異なっています。netifrc によって使用されるシンボリックリンクは再リンクする必要があるでしょう。追加したいインターフェース名それぞれに対して、リンク先として /etc/init.d/net.lo を使用してください。下のコマンド <interface_name> の部分はシステムに存在するイーサネットインターフェース名で置き換えてください。ip link コマンドを実行することで、どのインターフェースが存在するか発見することができます:
user $ip link存在する各インターフェースに対して /etc/init.d/ ディレクトリ内にシンボリックリンクを作成してください:
root #ln -s /etc/init.d/net.lo /etc/init.d/net.<interface_name>
すべてのインターフェースに関して必要な設定を /etc/conf.d/net に書いてください。
インターフェースを自動的に開始させるには、対応するスクリプトを default ランレベルに追加してください:
root #rc-update add net.<interface_name> default省略可能: 予測可能なネットワークインターフェース名を無効化または上書きする
カーネルによって提供される eth0 または wlan0 などのネットワークデバイス名は通常、/lib/udev/rules.d/80-net-setup-link.rules udev ルールおよび /lib/systemd/network/99-default.link 内の NamePolicy によって、システムブート時に変更されます (dmesg を確認してください)。
この挙動は複数の方法で無効化することができます:
- /etc/systemd/network/99-default.link に /dev/null へのシンボリックリンクを作成してください: ln -s /dev/null /etc/systemd/network/99-default.link。
- /etc/systemd/network 内に、インターフェースに別の名前を割り当てる .link ファイルをより小さい番号を付けて作成してください。
- カーネルコマンドラインに
net.ifnames=0を渡してください。
参照: https://systemd.io/PREDICTABLE_INTERFACE_NAMES/
キーとボタンの割り当てを変更する
udev は hwdb を使用してキーとボタンの割り当てを変更する方法を提供しています:
/etc/udev/hwdb.d/keyboard-example.hwdbevdev:name:AT Translated Set 2 keyboard:* KEYBOARD_KEY_db=58 # <16 進でのスキャンコード>=<10 進でのキーコードまたは 0x を先頭に付けた 16 進のキーコード>
The configuration syntax is very strict; the following must apply for each subentry:
- Key-value pairs are indented by at least one space character.
- String values - for example
KEY_CAPSLOCK- are written in lowercase. - Values are not quoted.
デバイス名は app-misc/evtest を使用して調べることができます:
root #evtest/dev/input/event3: AT Translated Set 2 keyboard
デバイスを選択して (evtest は対話的ツールです) キーを押すと、evtest はそのキーについての情報を表示します。この例では、押されたキーのスキャンコードは 0xDB であり、そのキーはキーコード 58 を持つキーを模倣しています:
Event: time 1708679751.175244, type 4 (EV_MSC), code 4 (MSC_SCAN), value db Event: time 1708679751.175244, type 1 (EV_KEY), code 58 (KEY_CAPSLOCK), value 1
キーコードの完全な一覧は Linux ソースコード内で確認できます。例として、#define KEY_CAPSLOCK 58 は 58 に変換されます。
キーボード以外のデバイスのキーコード (例: 左クリックマウスボタン 0x110) も許可されます。
変更を反映させるには、ハードウェアデータベース /etc/udev/hwdb.bin を更新しなくてはなりません (OpenRC にも対応しています):
root #systemd-hwdb update新しい構成は再起動後から有効になるでしょう。
Or by rebooting the system.
The device configuration can be verified like so:
root #udevadm info /dev/input/by-path/*usb*-kbd | grep "KEYBOARD_KEY"E: KEYBOARD_KEY_db=58
使い方
便利なコマンドをいくつか挙げると:
- すべての udev アクティビティを監視します:
root #udevadm monitor
- 与えられたデバイスファイルについてのすべてのメッセージを表示します:
root #udevadm info --query=all --name=/dev/DEVICE_FILE
- 与えられた sys path デバイスファイル (udevadm monitor を通じて取得できるかもしれません) についての udev 情報を表示します:
root #udevadm info --attribute-walk --path=/devices/DEVICE_FILE
- udev ルールファイルの例 - Ethernet デバイスに永続的な名前を割り当てます:
- ファイル
/etc/udev/rules.d/50-ethernet.rulesSUBSYSTEM=="net",ACTION=="add",ATTR{address}=="01:23:45:67:89:ab",NAME="ethernet0"
- /etc/udev/rules.d/ 内のルールファイルを変更した後は、再起動するか、以下のコマンドで udev に再読み込みさせます:
root #udevadm control --reload-rules
- 既に追加されているデバイス (接続済みの USB 等) に対しては、再読み込みされたルールは、デバイスを変更する (USB を接続し直す 等) か、udevadm trigger によって udev にカーネルイベントを再度リクエストさせることで反映されます。様々なイベントアクションを発動させることができます。デフォルトでは change イベントアクションが発動します:
root #udevadm trigger
さらなる情報は udevadm(8) の man page を読んでください。
トラブルシューティング
監視中のメッセージをログとして出力する
udevadm monitor を実行中のすべてのメッセージをログとして出力するには、次の設定ファイルを変更してください:
/etc/conf.d/udevudev_monitor="YES"
/run/udev/udevmonitor.log に新しいログファイルが作成されるでしょう。
デバッグモード
デバッグモードを有効にすると、詳細なメッセージをログに記録します:
/etc/conf.d/udevudev_debug="YES"
ロギングの優先順位を設定します:
/etc/udev/udev.confudev_log="debug"
ログファイル /run/udev/debug.log が作成されますが、メッセージはこのファイルに出力されないでしょう。最新版の udev はすべてのメッセージを dmesg に出力するでしょう。
デバイスファイル /dev/null と /dev/console が無い
一部の版の udev は、正しく動作するために /dev/null と /dev/console ファイルを必要としますが、自身でこれらを作成することができません。udev のためにこれらのファイルを手動で作成するには、次のコマンドを root 権限で実行してください:
root #mkdir test
root #mount --bind / test
root #cd test/dev
root #mknod -m 660 console c 5 1
root #mknod -m 660 null c 1 3
root #cd ../..
root #umount test
root #rmdir test
NIC に eth0 が割り当てられるが、eth1 に移動される
マザーボード上にデュアルネットワークカードを持っている場合、ip link が eth0 も eth1 も表示しない状況に陥ることがあるかもしれません。dmesg は、その NIC が eth0 として検出されたが、その後 eth1 に移動したことを示しているかもしれません。ip link を実行する場合も、その NIC は eth1 として表示されるでしょう。これは最初にカーネルによって割り当てられた名前を使用することによって発生します。ユーザは、lan0 や wireless0 のような自由な名前を使用するために、/etc/udev/rules.d/70-my-network.rules のようなカスタムルールを書くか、予測可能なインターフェース名を使用するべきです。
忘れずに、古いバージョンの udev に由来する古いファイルも削除してください:
root #rm /etc/udev/rules.d/70-persistent-net.rules /etc/udev/rules.d/80-net-setup-link.rules /etc/udev/rules.d/80-net-name-slot.rules /etc/systemd/network/99-default.linkまた、net.ifnames=0 をカーネルコマンドラインに渡していないことも確認してください。この設定は udev の予測可能なインターフェース名の機能を完全に無効化するでしょう。
ブート中にデバイスの準備が完了するのを待つ
ハードウェアによっては、デバイスがサービススクリプトによって必要とされた時点で利用可能になっていない場合があります。これは例えば、ネットワークインターフェースが利用可能であることを要求する、Netifrc を使用するときに起こることがあります。OpenRC はインターフェースが利用可能になるのを待つ方法を提供していないので、ERROR: interface wlan0 does not exist というメッセージで失敗し、競合状態になる場合があるでしょう。
すべてのデバイスが利用可能であることを確実にするには、sysinit 中に udev-settle サービスを開始してください。これによりブートには時間がかかるようになるでしょうが、rc_parallel が有効化されている場合は特に、より高い一貫性が提供されるでしょう:
root #rc-update add udev-settle sysinit