今回は「自宅サーバー」や「専用サーバー」向けの話題「Linuxのデバイス管理」について解説します。
デバイスとはパソコンに接続する周辺機器のことを言います。
例えば、「キーボード」「マウス」「プリンタ」「USBメモリ」「DVDドライブ」などだけでなく内蔵している「CPU」「メモリ」「HDD」もデバイスに含まれます。
Linuxのデバイス管理について
Linuxは、デバイス(周辺機器)もファイルで管理しています。
言葉を変えるとデバイスファイル(スペシャルファイル)としてデバイスを管理しています。
もともとはUNIXの思想で「デバイスもファイルとして扱う」というものです。
Linuxではデバイスファイルは自動的に作成されます。
作成されたデバイスファイルは「/dev」ディレクトリに配置されます。
/devディレクトリについて
/dev ディレクトリ配下のファイルは「キャラクタデバイス」と「ブロックデバイス」に分かれています。
昔は、あらかじめ全てのデバイスファイルを(不可能ですが)/dev ディレクトリ配下に作成する必要がありました。
しかしその後 /dev 配下のファイルは「動的」に管理されるようになりました。
キャラクタデバイス
キャラクタデバイスとは、「ランダムアクセスが不可能」なデバイスで、「キーボード」「マウス」「プリンタ」などが挙げられます。
ブロックデバイス
ブロックデバイスとは、バッファを持ち「ランダムアクセスが可能」な、ブロック単位でアクセスできるデバイスです。
「ハードディスク」「フロッピーディスク」「RAMディスク」「RAIDボリューム」などが挙げられます。
デバイスファイルとは
デバイスファイルとは、プログラム(catコマンドとかApacheとかMySQLなど)がLinuxマシン上のハードウェアデバイス(HWデバイス)に、カーネルを通してアクセスをするためのものです。
デバイスファイルは「ファイル」ではありません。
しかしプログラムからは「ファイル」に見えます。
つまり「読み出し」「書き出し」ができます。
プログラムがデバイスファイルにアクセスするとカーネルはI/O要求を認識して、そのプログラムにデバイスドライバを接続します。
その結果プログラムはデバイスにアクセスできるようになります。
udevがデバイスファイルを動的に作成する
私はパソコンにLinux(CentOS7)をインストールして使っていますが、今はUSBメモリを指せば動的に認識しますし、パソコンに付属している内蔵無線LANデバイスも動的に認識してデバイスドライバも動的にインストールします。
つまり、特に何もしなくてもOSインストール直後に無線LANがすぐに使えます。
なぜ動的にデバイスがカーネルに認識されるのかというと、udev が動的にデバイスファイルを作成しているからです。
先にも書きましたが、昔のLinuxは、あらかじめ全てのデバイスファイルを(不可能ですが)/dev ディレクトリ配下に作成する必要がありました。
もし/dev ディレクトリにデバイスファイルがない場合は、カーネルの再コンパイルをして対応していました。
しかし新しいデバイスを接続するたびに、カーネルの再コンパイルをするというのは、管理が非常に難しくごく一部のエンジニアしか使いこなせませんでした。
しかし udev は、必要なデバイスファイルを必要な時点で動的に生成することができます。
udevの歴史
udev の歴史について簡単に振り返ります。
udev はカーネルバージョン 2.5 から導入されました。
下図によると Linux Kernel Version 2.5は、2002年ごろです。
参考元:https://en.wikipedia.org/wiki/Linux_kernel
ちなみに2017年5月現在、CentOS7.3 のカーネルバージョンは「3.10.0-514」です。
-bash-4.2$ cat /etc/redhat-release -bash-4.2$ uname -r |
udevの内部動作
なぜデバイスをLinuxマシンに接続した瞬間に認識されるのでしょうか?
その理由は、udevd デーモンが Linuxマシンに新しいデバイスが接続されたかどうかカーネルを監視しているからです。
Linuxマシンにデバイスが接続されるとカーネルに検知されます。
その反応を udevd デーモンが監視をしています。
ただし udevd はユーザーアプリケーションなのでカーネル内のデータに直接アクセスできません。
そこで使われるのが sys ファイルシステム(sysfs)です。
sysfs は、カーネルのデバイス情報を提供します。
具体的には、カーネルが検出して初期化したデバイスについて、/sysディレクトリ以下にデバイス名の付いたディレクトリを作成します。
udevdはこのsysfsからデバイス情報を受け取ることでデバイスを管理することができます。
man udevの翻訳
何度もmanコマンドで「udev」について勉強できるように日本語訳を記載します。
(Google翻訳を利用しています)
-bash-4.2$ man udev | col -b NAME udev – 動的デバイス管理 DESCRIPTION udevはデバイスイベントをシステムソフトウェアに提供し、デバイスノードの権限を管理し、/ devディレクトリに追加のシンボリックリンクを作成するか、ネットワークインタフェースの名前を変更します。 The kernel usually just assigns unpredictable device names based on the order of discovery. カーネルは、通常、発見の順序に基づいて予測できないデバイス名を割り当てます。 The udev daemon, systemd-udevd.service(8), receives device uevents directly from the kernel whenever a device is added or removed from the system, or it changes its state. udevデーモン(systemd-udevd.service(8))は、デバイスがシステムに追加または削除されるたびにカーネルからデバイスueventsを直接受け取るか、またはデバイスの状態を変更します。 udevは、デバイスイベントを受信すると、設定されたルールのセットとさまざまなデバイス属性を照合してデバイスを識別します。 一致するルールは、udevデータベースに格納するか、意味のあるシンボリックリンク名を作成するために使用する追加のデバイス情報を提供します。 All device information udev processes is stored in the udev database and sent out to possible event subscribers. すべてのデバイス情報udevプロセスは、udevデータベースに格納され、可能なイベントサブスクライバに送信されます。 格納されたすべてのデータおよびイベントソースへのアクセスは、ライブラリlibudevによって提供されます。 RULES FILES udevルールは、システムルールディレクトリ/usr/lib/udev/rules.d、揮発性ランタイムディレクトリ/run/udev/rules.d、ローカル管理ディレクトリ/etc/udev/rules.dにあるファイルから読み込まれます。 すべてのルールファイルは、それらが存在するディレクトリに関係なく、語彙順にまとめてソートされ、処理されます。 ただし、同じファイル名のファイルは互いに置き換えられます。 /etc 内のファイルが最も優先度が高く、/run 内のファイルは /usr/lib 内の同じ名前のファイルよりも優先されます。 これは、必要に応じてシステム提供のルールファイルをローカルファイルで上書きするために使用できます。 /dev/nullを指す /usr/lib 内の rules ファイルと同じ名前の /etc 内のシンボリックリンクは、rulesファイルを完全に無効にします。 ルールファイルの拡張子は.rulesでなければなりません。 他の拡張子は無視されます。 Every line in the rules file contains at least one key-value pair. rulesファイルの各行には少なくとも1つのキーと値のペアが含まれています。 空行または “#”で始まる行を除き、無視されます。 2種類のキーがあります:一致と割り当て。 すべての一致キーがその値と一致する場合、ルールが適用され、割り当てキーには指定された値が割り当てられます。 A matching rule may rename a network interface, add symlinks pointing to the device node, or run a specified program as part of the event handling. マッチングルールは、ネットワークインタフェースの名前を変更したり、デバイスノードを指すシンボリックリンクを追加したり、イベント処理の一部として指定されたプログラムを実行することができます。 A rule consists of a comma-separated list of one or more key-value pairs. Each key has a distinct operation, depending on the used operator. Valid operators are: ルールは、1つ以上のキーと値のペアのカンマ区切りのリストで構成されます。 それぞれのキーは、使用される演算子に応じて異なる操作をします。 有効な演算子は次のとおりです。 “==” 平等のための比較
“!=” 不等式の比較 “=” キーに値を割り当てます。 リストを表すキーはリセットされ、この単一の値だけが割り当てられます。 “+=” エントリのリストを保持するキーに値を追加します。 “-=” エントリのリストを保持するキーから値を削除します。 “:=” 最後にキーに値を割り当てます。 後で変更を許可しない。 The following key names can be used to match against device properties. Some of the keys also match against properties of the parent devices in sysfs, not only the device that has generated the event. 次のキー名を使用して、デバイスのプロパティと一致させることができます。 一部のキーは、イベントを生成したデバイスだけでなく、sysfsの親デバイスのプロパティとも一致します。 親デバイスと一致する複数のキーが1つのルールで指定されている場合、これらのキーはすべて1つの同じ親デバイスで一致する必要があります。 ACTION イベントアクションの名前と一致します。 DEVPATH イベントデバイスのdevpathと一致します。 KERNEL イベントデバイスの名前と一致します。 NAME ネットワークインターフェイスの名前と一致します。 上記のルールのいずれかでNAMEキーが設定されていれば使用できます。 SYMLINK ノードを対象とするシンボリックリンクの名前と一致させます。 前述の規則の1つにSYMLINKキーが設定されている場合に使用できます。 複数のシンボリックリンクが存在する可能性があります。 1つだけ一致する必要があります。 SUBSYSTEM イベントデバイスのサブシステムに一致します。 DRIVER イベントデバイスのドライバ名を一致させます。 イベント発生時にドライバにバインドされているデバイスに対してのみ、このキーを設定します。 ATTR{filename} イベントデバイスのsysfs属性値と一致します。 指定された一致値に末尾の空白が含まれていない限り、属性値の末尾の空白は無視されます。 KERNELS devpathを上向きに検索し、一致するデバイス名を探します。 SUBSYSTEMS devpathを上向きに検索し、一致するデバイス・サブシステム名を探します。 DRIVERS devpathを上向きに検索して、一致するデバイスドライバ名を探します。 ATTRS{filename} sysfsの属性値が一致するデバイスがあるかどうか検索します。 複数のATTRS一致が指定されている場合、それらのすべてが同じデバイス上で一致する必要があります。 指定された一致値に末尾の空白が含まれていない限り、属性値の末尾の空白は無視されます。 TAGS タグが一致するデバイスを検索する。 ENV{key} デバイスのプロパティ値と照合します。
TAG デバイスタグと照合します。 TEST{octal mode mask} ファイルの存在をテストします。 必要に応じて、8進モードのマスクを指定できます。 PROGRAM プログラムが実行され、一致するかどうかが判断されます。 プログラムが正常に戻ると、キーはtrueになります。 デバイスのプロパティは、環境内の実行されたプログラムで使用できるようになります。 The program’s standard output is available in the RESULT key. プログラムの標準出力はRESULTキーで利用できます。 This can only be used for very short-running foreground tasks. これは非常に短期間のフォアグラウンドタスクにのみ使用できます。 詳細は、RUNを参照してください。 RESULT 最後のPROGRAM呼び出しの戻り文字列と一致します。 このキーは、PROGRAM呼び出し後の同じルールまたは後のルールで使用できます。 Most of the fields support shell glob pattern matching and alternate patterns. ほとんどのフィールドはシェルのglobパターンのマッチングと代替パターンをサポートしています。 次の特殊文字がサポートされています。 “*” ゼロ個以上の文字に一致します。 “?” 任意の1文字に一致します。 “[]” 角括弧内に指定された任意の1文字と一致します。 たとえば、パターン文字列 “tty [SR]”は “ttyS”または “ttyR”と一致します。 範囲は ” – “文字でもサポートされています。 たとえば、すべての桁の範囲を一致させるには、パターン “[0-9]”を使用できます。 “[“が “!”の後の最初の文字は、囲まれていない文字と一致します。 “|” 別のパターンを区切ります。 たとえば、パターン文字列 “abc | x *”は “abc”または “x *”と一致します。 The following keys can get values assigned: 次のキーで値を割り当てることができます。 NAME ネットワークインタフェースに使用する名前。 インタフェース名を設定する上位レベルのメカニズムについては、systemd.link(5)を参照してください。 デバイスノードの名前はudevで変更することはできません。追加のシンボリックリンクだけを作成することができます。 SYMLINK ノードをターゲットとするシンボリックリンクの名前。 すべてのマッチングルールは、作成するシンボリックリンクのリストにこの値を追加します。 The set of characters to name a symlink is limited. シンボリックリンクに名前を付ける一連の文字は限られています。 有効な文字は “0-9A-Za-z#+ – 。:= @ _ /”、有効なUTF-8文字シーケンス、および “\ x00” 16進エンコーディングです。 他のすべての文字は “_”文字に置き換えられます。 Multiple symlinks may be specified by separating the names by the space character. 複数のシンボリックリンクは、スペース文字で名前を区切って指定することができます。 複数のデバイスが同じ名前を主張する場合、リンクは常に最も高いlink_priorityを持つデバイスを指します。 現在のデバイスが消えた場合、リンクは再評価され、次に高いlink_priorityを持つデバイスがリンクの所有者になります。 link_priorityが指定されていない場合、デバイスの順序(およびそのリンクのいずれかが所有されているか)は未定義です。 Symlink names must never conflict with the kernel’s default device node names, as that would result in unpredictable behavior. Symlinkの名前は、カーネルのデフォルトのデバイス・ノード名と決して衝突してはなりません。その結果、予期しない動作が発生します。 OWNER, GROUP, MODE デバイスノードのアクセス許可。 指定された値はすべて、コンパイルされたデフォルト値を上書きします。 SECLABEL{module} 指定したLinuxセキュリティモジュールのラベルをデバイスノードに適用します。 ATTR{key} イベントデバイスのsysfs属性に書き込まれる値。 ENV{key} デバイスプロパティ値を設定します。 先頭に “.”が付いたプロパティ名 データベースに格納されず、イベントや外部ツール(PROGRAM一致キーなどによって実行される)にもエクスポートされません。 TAG デバイスにタグを付けます。 これは、libudevのモニタ機能のユーザのためのイベントをフィルタリングするため、またはタグ付きデバイスのグループを列挙するために使用されます。 実装は、デバイスに少数のタグだけが接続されている場合にのみ効率的に機能します。 これは、特定のデバイスフィルタ要件を持つコンテキストでのみ使用され、汎用フラグとしては使用されません。 過度に使用すると、効率の悪いイベント処理が行われる可能性があります。 RUN{type} 「タイプ」に応じて、特定のイベントのすべてのルールを処理した後に実行するプログラムのリストにプログラムを追加します。 “program” 割り当てられた値として指定された外部プログラムを実行します。 絶対パスが指定されていない場合、プログラムは /usr/lib/udev に存在するはずです。 それ以外の場合は、絶対パスを指定する必要があります。 This is the default if no type is specified. タイプが指定されていない場合のデフォルトです。 “builtin” プログラムとしては、外部プログラムではなく組み込みプログラムの1つを使用します。 The program name and following arguments are separated by spaces. プログラム名とそれに続く引数はスペースで区切られます。 スペースで引数を指定するには、一重引用符を使用できます。 This can only be used for very short-running foreground tasks. これは非常に短期間のフォアグラウンドタスクにのみ使用できます。 長期間にわたってイベントプロセスを実行すると、このデバイスまたは従属デバイスの今後のイベントがすべてブロックされる可能性があります。 Starting daemons or other long-running processes is not appropriate for udev; the forked processes, detached or not, will be unconditionally killed after the event handling has finished. デーモンやその他の長時間実行されるプロセスの起動は、udevでは適切ではありません。 分離されたかどうかにかかわらず、フォークされたプロセスは、イベントの処理が完了した後で無条件に終了します。 LABEL GOTOがジャンプする可能性のある名前付きラベル。 GOTO
IMPORT{type} 「タイプ」に応じて、デバイスプロパティとして変数のセットをインポートします。 “program” 割り当てられた値として指定された外部プログラムを実行し、その出力をインポートします。これは環境キー形式でなければなりません。 パス仕様、コマンド/引数分離、およびRUNのような引用作業。 “builtin” “プログラム”と似ていますが、外部プログラムではなく組み込みプログラムの1つを使用します。 “file” 割り当てられた値として指定されたテキストファイルをインポートします。その内容は環境キー形式でなければなりません。 “db” 現在のデバイスデータベースから、割り当てられた値として指定された1つのプロパティをインポートします。 これは、以前のイベントによってデータベースがすでに設定されている場合にのみ機能します。 “cmdline” カーネルのコマンドラインから単一のプロパティーをインポートします。 単純なフラグの場合、プロパティの値は “1”に設定されます。 “parent” 親デバイスのデータベースエントリを読み取ることによって、親デバイスから格納されたキーをインポートします。 IMPORT {parent}に割り当てられた値は、インポートするキー名のフィルタとして使用されます(比較に使用される同じシェルのglobパターンマッチングで)。 This can only be used for very short-running foreground tasks. For details see RUN. これは非常に短期間のフォアグラウンドタスクにのみ使用できます。 詳細については、RUNを参照してください。 WAIT_FOR ファイルが使用可能になるのを待つか、タイムアウトが10秒になるまで待ちます。 パスはsysfsデバイスとの相対パスです。 パスが指定されていない場合は、属性が表示されるのを待ちます。 OPTIONS ルールとデバイスのオプション: link_priority=value 作成されたシンボリックリンクの優先度を指定します。 高い優先順位を持つデバイスは、他のデバイスの既存のシンボリックリンクを上書きします。 デフォルトは0です。
string_escape=none|replace 通常、制御やその他のおそらく危険な文字は、デバイスの命名に使用される文字列に置き換えられます。 このオプションで置換モードを指定することができます。 static_node= このルールで指定された権限を、指定された名前の静的デバイスノードに適用します。 また、このルールで指定されたすべてのタグについて、指定された名前を持つ静的デバイスノードを指す/ run / udev / static_node-tags /タグディレクトリにシンボリックリンクを作成します。 静的デバイスノードの作成は、systemd-udevdが起動する前にsystemd-tmpfilesによって実行されます。 静的ノードには、対応するカーネルデバイスがない可能性があります。 それらがアクセスされたときにカーネルモジュールの自動ロードを起動するために使用されます。 watch inotifyでデバイスノードを監視する。 書き込みのためにノードを開いた後にノードを閉じると、変更イベントが合成されます。 nowatch inotifyでデバイスノードの監視を無効にする。 The NAME, SYMLINK, PROGRAM, OWNER, GROUP, MODE, and RUN fields support simple string substitutions. NAME、SYMLINK、PROGRAM、OWNER、GROUP、MODE、およびRUNフィールドは、単純な文字列の置換をサポートします。 RUN置換は、プログラムが実行される直前にすべてのルールが処理された後に実行され、以前の一致ルールによって設定されたデバイスプロパティの使用を可能にする。 他のすべてのフィールドでは、個々のルールが処理されている間に置換が実行されます。 使用可能な置換は次のとおりです。 $kernel, %k このデバイスのカーネル名。 $number, %n このデバイスのカーネル番号。 たとえば、 “sda3″はカーネル番号 “3”を持ちます。 $devpath, %p デバイスのdevpath。 $id, %b SUBSYSTEMS、KERNELS、DRIVERS、ATTRSのためにdevpathを上向きに検索している間にマッチしたデバイスの名前。 $driver SUBSYSTEMS、KERNELS、DRIVERS、ATTRSのためにdevpathを上向きに検索しながら、デバイスのドライバ名が一致しました。 $attr{file}, %s{file} ルールのすべてのキーが一致したデバイスで検出されたsysfs属性の値。 一致するデバイスにこのような属性がなく、以前のKERNELS、SUBSYSTEMS、DRIVERS、またはATTRSテストで親デバイスが選択されている場合、その親デバイスの属性が使用されます。 If the attribute is a symlink, the last element of the symlink target is returned as the value. 属性がシンボリックリンクの場合、シンボリックリンクターゲットの最後の要素が値として返されます。 $env{key}, %E{key} デバイスプロパティ値。 $major, %M デバイスのカーネルメジャー番号。 $minor, %m デバイスのカーネルマイナー番号。 $result, %c PROGRAMで要求された外部プログラムから返された文字列。 スペース文字で区切られた文字列の単一の部分は、部品番号を属性 “%c {N}”として指定することによって選択することができます。 数字の後に “+”文字が続く場合、この部分と結果文字列の残りの部分は “%c {N +}”で置き換えられます。 $parent, %P 親デバイスのノード名。 $name デバイスの現在の名前。 ルールによって変更されていない場合は、カーネルデバイスの名前です。 $links 現在のシンボリックリンクのスペースで区切られたリスト。 この値は、削除イベント中に設定されるか、以前のルールで値が割り当てられている場合にのみ設定されます。 $root, %r udev_rootの値。 $sys, %S sysfsマウントポイント。 $devnode, %N デバイスノードの名前。 %% “%”文字自体。 $$ “$”文字自体。 SEE ALSO systemd 219 UDEV(7) |
コメント