Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationEventAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
77
Help us understand the problem. What are the problem?

More than 1 year has passed since last update.

posted at

updated at

udevルールの書き方

1 udevとは?

udevはデバイスファイルを動的に作成、削除する仕組みです。
以下にデバイスファイルを作成するまでの流れを示します。
(1) カーネルがデバイスの追加、削除を検知
(2) /sys配下にデバイスの情報を反映
(3) udevdにイベント通知(Netlinkでイベント通知)
(4) udevdは、/sys配下の情報とudevルールを参照
(5) (4)の結果にもとづいて、デバイスファイルを作成

デバイスファイルファイル作成までの全体の流れ
+-----------------------------+
|   udev rule                 |
|     /usr/lib/udev/rules.d   |
|     /etc/udev/rules.d       |
+-----------------------------+
             A
             |
             | (4)参照
             |                                      (5)デバイスファイル作成
+-----------------------------+                       +---------------+
|          udevd              |---------------------->|               |
+-----------------------------+                       +---------------+
             A            |
             |            | (4)参照
             |            |                           +---------------+
        (3)uevent         +-------------------------->|     /sys      |
             |                                        +---------------+
             |                                                A
             |                                                | (2)デバイス情報作成
             |                                                |
+---------------------------------------------------------------------+
|                                Kernel                               |
+---------------------------------------------------------------------+
                                  A
                                  |
                                  |  (1) カーネルがデバイスの追加、削除を検知

2 環境

VMware Workstation 14 Player上の仮想マシンを使いました。

OS版数
[root@server ~]# cat /etc/redhat-release
CentOS Linux release 7.4.1708 (Core)

[root@server ~]# uname -r
3.10.0-693.el7.x86_64

3 ルールの概要

3.1 ルールファイルの保存場所

udevのルールファイルは、以下の場所に保存されていいます。
本記事では、/etc/udev/rules.d配下にルールを作成します。

パス 概要
/usr/lib/udev/rules.d デフォルトのルールが保存されている場所
/etc/udev/rules.d デフォルトルールをカスタマイズしたルールを置く場所

/usr/libはデフォルト、/etcはカスタマイズしたものを置く、
という考え方はsystemdのUNIT定義ファイルと同じですね。

3.2 ルールファイルの規則

・ルールファイルの拡張子は、.rulesになります。
・ルールファイルの名前は、数字-名前から構成されます。 (例) 50-udev-default.rules
・ルールファイルの中身のルールは、カンマで区切られたkey-valueペアで構成されています。
==で検索条件、=でアクションを指定します。
全ての検索条件に一致したら、アクションを実行します。

ルールの構成
         検索条件                     アクション
|<------------------------->|  |<---------------->|
XX=="xx", YY=="yy", ZZ=="zz",    AA="aa", BB="bb"

(注) "アクション"という言葉は正式な用語ではないかもしれません。ここでは便宜上使用しています。

4 ループデバイスを使った実験

ここでは、ループデバイスに関する、udevルールを作成してみます。

4.1 事前準備

ループデバイスを作成するため、事前にファイルを作成しておきます。
ファイルサイズは1Gである必要はありません。適当なサイズを指定してください。

ファイルの作成
[root@server ~]# fallocate -l 1G disk1.img
[root@server ~]# fallocate -l 1G disk2.img
[root@server ~]# ls -l disk*
-rw-r--r--. 1 root root 1073741824  1月 19 21:34 disk1.img
-rw-r--r--. 1 root root 1073741824  1月 19 21:34 disk2.img

4.2 実行例

ループデバイス(loop0)を検出したら、loggerコマンドを実行する、というルールを作成します。
loggerコマンドは、"loop0"という文字列をログに出力します。

ターミナル1(udevルールの作成)
[root@server ~]# vi /etc/udev/rules.d/10-test.rules
[root@server ~]# cat /etc/udev/rules.d/10-test.rules
KERNEL=="loop0", RUN="/usr/bin/logger loop0"

ログの出力を確認するため、journalctlコマンドを実行します。

ターミナル2
[root@server ~]# journalctl -f

ループデバイスを作成します。
なお、losetupコマンドの使い方は、ここ(losetupコマンドの使い方)を参照ください。

ターミナル1(ループデバイスの作成)
[root@server ~]# losetup -f /root/disk1.img

作成したループデバイスを確認します。

ターミナル1(ループデバイスの確認)
[root@server ~]# losetup -l
NAME       SIZELIMIT OFFSET AUTOCLEAR RO BACK-FILE
/dev/loop0         0      0         0  0 /root/disk1.img

次にログを確認します。
udevルールにしたがって、loggerコマンドが実行されていることがわかります。
なお、journalctlコマンドの使い方は、ここ(journalctl コマンドの使い方)を参照ください。

ターミナル2
[root@server ~]# journalctl -f
 1月 19 21:51:23 server systemd-udevd[425]: Network interface NamePolicy= disabled on kernel command line, ignoring.
 1月 19 21:51:23 server root[7400]: loop0
 1月 19 21:51:23 server root[7401]: loop0

ループデバイスを削除します。

ターミナル1(後始末)
[root@server ~]# losetup -D
[root@server ~]# losetup -l
[root@server ~]#

5 置換(substitution)の使い方

5.1 デバイスパスを表示する方法(%p)

デバイスパスは、/sys配下に作成されます。%pはデバイスパスに置換されます。
ここで作成するルールは、loopデバイス(*)を検出したら、loggerコマンドを実行します。
loggerコマンドで、loopデバイスのデバイスパスを表示します。
(*)loopデバイスのマイナ番号は0,1,2...に一致したものになります。

ターミナル1(udevルールの作成)
[root@server ~]# vi /etc/udev/rules.d/10-test.rules
[root@server ~]# cat /etc/udev/rules.d/10-test.rules
KERNEL=="loop*", RUN="/usr/bin/logger %p"

ループデバイスを作成します。

ターミナル1(ループバックデバイスの作成)
[root@server ~]# losetup -f /root/disk1.img
[root@server ~]# losetup -f /root/disk2.img

ログを確認すると、%pがデバイスパスに置換されたことがわかります。

ターミナル2
[root@server ~]# journalctl -f
 1月 19 22:39:12 server root[7555]: /devices/virtual/block/loop0
 1月 19 22:39:12 server root[7556]: /devices/virtual/block/loop0
 1月 19 22:39:15 server root[7560]: /devices/virtual/block/loop1
 1月 19 22:39:15 server root[7561]: /devices/virtual/block/loop1

5.2 デバイスの名前を表示する方法(%k)

ルールを作成します。
%kはデバイスの名前に置換されます。

ターミナル1(udevルールの作成)
[root@server ~]# vi /etc/udev/rules.d/10-test.rules
[root@server ~]# cat /etc/udev/rules.d/10-test.rules
KERNEL=="loop*", RUN="/usr/bin/logger %k"

ループデバイスを作成します。

ターミナル1(ループデバイスの作成)
[root@server ~]# losetup -f /root/disk1.img

ログを確認すると、%kが"loop0"に置換されたことがわかります。

ターミナル2
[root@server ~]# journalctl -f
 1月 20 17:13:20 server root[5952]: loop0
 1月 20 17:13:20 server root[5953]: loop0

5.3 デバイスのプロパティを表示する方法

ここでは、デバイスのプロパティとして、メジャー番号、マイナー番号を表示してみます。
udevadm info -eを実行することで、メジャー番号、マイナー番号を確認することができます。

ターミナル1(udevルールの作成)
[root@server ~]# vi /etc/udev/rules.d/10-test.rules
[root@server ~]# cat /etc/udev/rules.d/10-test.rules
KERNEL=="loop*", RUN="/usr/bin/logger $env{MAJOR}:$env{MINOR}"

ループデバイスを作成します。

ターミナル1(ループバックデバイスの作成)
[root@server ~]# losetup -f /root/disk1.img
[root@server ~]# losetup -f /root/disk2.img

ログを確認すると、$env{MAJOR}:$env{MINOR}が、7:0,7:1に置換されたことがわかります。

ターミナル2
[root@server ~]# journalctl -f
 1月 20 17:35:45 server root[6002]: 7:0
 1月 20 17:35:45 server root[6003]: 7:0
 1月 20 17:35:49 server root[6007]: 7:1
 1月 20 17:35:49 server root[6008]: 7:1

6 検索条件の使い方

今までは、デバイスの検索条件としてKERNELを使ってきました。
検索条件の絞り込みに使えるキーワードは、他にSUBSYSTEM,DRIVER,ENV等があります。
詳細は、man udevを参照ください。

ここでは、ここ(カーネルモジュールの作り方「11.デバイスの登録、削除」)にある
プログラムを使って、検索条件の絞り込みを確認してみます。

6.1 SUBSYSTEMを使った絞り込み

ルールを作成します。
KERNELに加え、SUBSYSTEMも検索条件に加えます。
両方の検索条件に一致すると、loggerコマンドを実行します。

なお、KERNELやSUBSYSTEMに指定する文字列は、
udevadm info -eを実行することで確認することができます。

ターミナル1(udevルールの作成)
[root@server modules]# cat /etc/udev/rules.d/10-test.rules
KERNEL=="test_device", SUBSYSTEM=="misc", RUN="/usr/bin/logger %k"

ログの出力を確認するため、journalctlコマンドを実行します。

ターミナル2
[root@server ~]# journalctl -f
ターミナル1(モジュールのインストール)
[root@server modules]# insmod test.ko
ターミナル2
[root@server ~]# journalctl -f
 1月 21 18:33:48 server kernel: Device registered!
 1月 21 18:33:48 server root[7746]: test_device

6.2 ENVを使った絞り込み

ルールを作成します。
KERNEL,SUBSYSTEMに加え、MAJOR/MINORも検索条件に加えます。
なお、udevadm info -eを実行すると、MAJOR/MINORの値が確認できます。

ターミナル1(udevルールの作成)
[root@server ~]# cat /etc/udev/rules.d/10-test.rules
KERNEL=="test_device", SUBSYSTEM=="misc", ENV{MAJOR}=="10", ENV{MINOR}=="55", RUN="/usr/bin/logger %k"

7 アクションの使い方

7.1 OWNER,GROUP,MODEの使い方

OWNER,GROUP,MODEを使うと、
デバイスファイルにオーナ、グループ、モードを設定することができます。
ここでは、test_deviceを検出したら、デバイスファイルのモードに0644を設定してみます。
また、そのとき、loggerコマンドを実行してみます。

ターミナル1(udevルールの作成)
[root@server ~]# vi /etc/udev/rules.d/10-test.rules
[root@server ~]# cat /etc/udev/rules.d/10-test.rules
KERNEL=="test_device", MODE="0644", RUN="/usr/bin/logger %k"

ログの出力を確認するため、journalctlコマンドを実行します。

ターミナル2
[root@server ~]# journalctl -f

コンパイルしたモジュールをインストールします。

ターミナル1
[root@server modules]# insmod test.ko

ログを確認する。

ターミナル2
[root@server ~]# journalctl -f
 1月 21 17:36:56 server kernel: Device registered!
 1月 21 17:36:56 server root[7488]: test_device

デバイスファイルのモードが0644になっていることがわかります。

ターミナル1(実行結果の確認)
[root@server modules]# ls -l /dev/test_device
crw-r--r--. 1 root root 10, 55  1月 21 18:07 /dev/test_device

ログの出力を確認するため、journalctlコマンドを実行します。

ターミナル2
[root@server ~]# journalctl -f

コンパイルしたモジュールをインストールします。

ターミナル1
[root@server modules]# insmod test.ko

7.2 NAMEの使い方

ルールを作成する。
br0ならtest-br0,br1ならtest-br1という名前のデバイスファイルを作成します。

ターミナル1(udevルールの作成)
[root@server ~]# vi /etc/udev/rules.d/10-test.rules
[root@server ~]# cat /etc/udev/rules.d/10-test.rules
KERNEL=="br*", NAME="test-br%n"

br0という名前のブリッジデバイスを作成する。
udevルールにしたがって、test-br0という名前のデバイスが作成されています。

ブリッジデバイスの作成
[root@server ~]# ip link add br0 type bridge
[root@server ~]# ip l
(中略)
10: test-br0: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN mode DEFAULT group default qlen 1000
    link/ether 16:bf:9e:8e:f7:4e brd ff:ff:ff:ff:ff:ff

br1という名前のブリッジデバイスを作成する。
udevルールにしたがって、test-br1という名前のデバイスが作成されています。

ブリッジデバイスの作成
[root@server ~]# ip link add br1 type bridge
[root@server ~]# ip l
(中略)
10: test-br0: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN mode DEFAULT group default qlen 1000
    link/ether 16:bf:9e:8e:f7:4e brd ff:ff:ff:ff:ff:ff
11: test-br1: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN mode DEFAULT group default qlen 1000
    link/ether 6e:e2:ee:de:2e:ac brd ff:ff:ff:ff:ff:ff

作成したブリッジデバイスを削除します。

後始末
[root@server ~]# ip l del test-br0
[root@server ~]# ip l del test-br1

Z 参考情報

Linux教科書 LPICレベル2 スピードマスター問題集

第555回 いま,あらためてudev
第559回 デバイスの認識をモニタリング・コントロールできる「udevadm」
Writing udev rules
udev ルールの書き方
11.0 udevを使用した動的カーネルデバイス管理
udevルールの設定(Red Hat Enterprise Linux server 6以降の場合)
udev の設定をカスタマイズする
udev をもっとカスタマイズする
Tutorial on how to write basic udev rules in Linux
第15回 udevを読む
udevadm command examples
USBにドライブが接続されたら自動的にバックアップを作成したい
udevのruleファイルについて

How to set custom device names using udev in CentOS/RHEL 7

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
77
Help us understand the problem. What are the problem?