メジャー/マイナー番号のペアでデバイスノードを取得する


12

配下の各デバイスノードに/devは、独自のメジャー/マイナー番号のペアがあります。次のように、を使用してデバイスノードからこの番号のペアを取得できることを知っていますstat

stat -c 'major: %t minor: %T' <file>

または、ls -lこれらの数値も表示されます。

しかし、メジャー番号とマイナー番号を指定してデバイスノードを取得するにはどうすればよいですか?私の知る唯一の方法は、いくつかの種類であるls -l+ awkトリックが、私は本当によりよい解決策があると願っています。


@mikeserv、はい、一部のデバイスはこれらの番号を共有できることを知っているので、最初の質問で、「デバイスノードを取得」と述べました。理想的には、メジャー/マイナー番号が一致するすべてのデバイスノードのリストを1行に1つ取得したいと考えています。そのための準備が整ったツールがないのは奇妙です。回答をありがとうございます。
ドミトリーフランク

回答:


7

私が使用して単純なアプローチ見つけSYSで、pseudofilesystemを/ SYS / devのあなたはデバイスがその後、メジャー/マイナーで、ファイルの種類によって命じていUEVENTは、デバイス名とその他の情報の束が含まれています。

たとえば

  for file in $(find /sys/dev/ -name 7:0); do  
      source ${file}/uevent; echo $DEVNAME;
  done;

エコーズ、

loop0
vcs

注:これはDebian Wheezyでテストされました


for file in $(ls /sys/dev/block/ ); do source /sys/dev/block/${file}/uevent; if [ "$DEVNAME" == "sda1" ] ; then echo ${file}; fi done;
開発者

5

よく分からない。

mknod foo b 8 0

fooメジャー8とマイナー0のブロックデバイスと呼ばれるデバイスファイルを作成します。/dev同じタイプのメジャーとマイナーを持つ1つまたはいずれかのファイルを見つける場合は、(を使用してzsh)実行できます。

  • ブロックデバイスの場合8:0

    $ zmodload zsh/stat
    $ ls -ld /dev/**/*(-D%be:'zstat -H s $REPLY && (($s[rdev] == 8<<8+0))':)
    lrwxrwxrwx 1 root root    6 Aug 23 05:28 /dev/block/8:0 -> ../sda
    lrwxrwxrwx 1 root root    9 Aug 23 05:28 /dev/disk/by-id/ata-KINGSTON_SNV455S234GB_07MA10014418 -> ../../sda
    brw-rw---- 1 root disk 8, 0 Aug 23 05:28 /dev/sda
    
  • charデバイスの場合226:0

    $ ls -ld /dev/**/*(-D%ce:'zstat -H s $REPLY && (($s[rdev] == 226<<8+0))':)
    lrwxrwxrwx  1 root root      12 Aug 23 05:28 /dev/char/226:0 -> ../dri/card0
    crw-rw----+ 1 root video 226, 0 Aug 23 05:28 /dev/dri/card0
    

で何でもファイルを作成できることに注意してください/dev。非常に昔は、そこに静的ファイルを作成するスクリプトでした。ある時点で、特別なファイルシステムアラがあったこともあります/proc

最近のバージョンのLinuxでは、通常udev、カーネルからの入力に基づいています。

ベースデバイスファイル用に選択する名前はDEVNAME、カーネルによって提供される名前に基づいています。udevルールはそれを変更するかもしれませんが、一般的には変更しません、そしていくつかのudevルールは便利のためにいくつかのシンボリックリンクを追加します(の/dev/disk/by...もののように)。

あなたはmajor:minorからカーネルに行くことができますDEVNAME

$ sed -n 's/^DEVNAME=//p' /sys/dev/block/8:0/uevent
sda
$ sed -n 's/^DEVNAME=//p' /sys/dev/char/226:0/uevent
dri/card0

udevmikeservが示したように、データベースからその情報を取得することもできます。


5

どうやらそれはを使ってもっと簡単にできるudevadmと思います、そして私はちょうどその方法を見つけました。

あなたDEVNAMEから得るためにはudevadmあなたはただ行う必要があります:

udevadm info -rq name $PATH

たとえば、/dev名前を知りたい場合は、次のようにします/sys/dev/char/5:1

udevadm info -rq name /sys/dev/char/5:1

出力

/dev/console

-rオプションを指定することで--root、それなしで読み取り専用です上記の結果を-エド・パスをconsole-qオプションは、データベースを指定--queryし、それがオペランドを取りname、ここで-私たちはしたいのでDEVNAME

major:minor番号のみを指定してcharやブロックデバイスへのパスを見つける非常に簡単な方法は次のようになります。

mmdev() for d in /sys/dev/[cb]*/$1:$2
        do  [ -e "$d" ] || return
            printf %c:%s: "${d#/*/*/}" "${d##*/}"
            udevadm info -rq name "$d"
        done

だから実行中:

mmdev 8 0

プリント...

b:8:0:/dev/sda

これが最初に書いたものです。

majminpath() {
    set -- ${1##*[!0-9]*} ${2##*[!0-9]*}
    udevadm info --export-db |
    sed 's|^[^=]*DEVNAME=||
         \|^[^/]|!h;/MAJOR=/N
         \|='"$1\n.*=${2?}"'$|!d;g'
}

これudevadm info --export-dbは、一致する数値の出力をスキャンするだけです。出力は次のようになります。

P: /devices/virtual/vc/vcsa4
N: vcsa4
E: DEVNAME=/dev/vcsa4
E: DEVPATH=/devices/virtual/vc/vcsa4
E: MAJOR=7
E: MINOR=132
E: SUBSYSTEM=vc

P: /devices/virtual/vc/vcsa5
N: vcsa5
E: DEVNAME=/dev/vcsa5
E: DEVPATH=/devices/virtual/vc/vcsa5
E: MAJOR=7
E: MINOR=133
E: SUBSYSTEM=vc

#...and so on

ワークフローは次のようなものです。

  • [^=]*DEVNAME=各行の先頭から文字列を取り除こうとします

  • 行に最初の文字がないか、最初の文字が古い/行にその行をコピーするh場合

  • 行がパターンスペースにMAJOR=追加N入力行を追加する場合に一致します

  • パターンスペースに一致する2行がある場合は=$1\n.*=$2$h古いスペースをパターンスペースにコピーして自動印刷します。そうでなければパターンスペースを削除

だから私がするなら:

majminpath 7 133 ; majminpath 8 0 ; majminpath 8 1

出力

/dev/vcsa5
/dev/sda
/dev/sda1

しかし、@ xaeが指摘するように、block / charタイプのデバイスはmaj:minの組み合わせを共有できるため、これにより、1回の呼び出しで複数のパスが出力される可能性があります。


1
残念ながら、それはそれほど簡単ではありません。ブロックとキャラクターデバイスは同じメジャー番号を共有できます。/ proc / devicesファイルを見てください。
xae 2014

サブシステムをチェックする必要があります-そうです。ありがとう、@ xae。
mikeserv 2014

1

悲しいかな/sys/dev階層にカーネルが追加されたのは遅くとも2.6.27(カーネルのコードベースに対する関連するコミットを参照)なので、「分岐」アプローチが必要です。

ましょう$M$m、それぞれ、私たちのデバイスファイルのメジャーとマイナー番号です。

投稿 2.6.27カーネルを

他の人が示唆しているように、最も簡単なアプローチは、フォルダーの下にsysfs名前が付けられたファイルを直接追跡することにより、「仮想」ファイルシステムの能力を発揮$M:$mします/sys/dev(デバイスがキャラクターであるかどうかわからない場合、複数のファイルが予想されます-またはブロックベースのueventファイル)、次にファイルをソースします(名前空間の汚染を防ぐためにサブシェルで):

for file in $(find /sys/dev/ -name $M:$m)
do
    (
        source ${file}/uevent
        echo $DEVNAME
    )
done

2.6.27より前のカーネル

簡単にするために、ファイルがブロックデバイスであると仮定します(同様のアプローチがキャラクターデバイスに適用されます)。名前がたまたまであるすべてのファイルの内容を(そのフォルダーの下で)調べることにより$M:$m/sys/block階層全体で文字列を検索しますdev/sys/block/<...>/<DEV>/devがそのようなファイルである場合DEV、デバイスの名前にバインドされます。

dirname "$(find "/sys/block" -name dev | xargs -r grep -l ^$M:$m$)"

0

Linuxでは、/proc仮想ファイルシステムの特定のファイルを利用することが可能です。

$ grep '8[[:blank:]]\+1[[:blank:]]\+' /proc/partitions 
   8        1   29309568 sda1

$ grep '8:1[[:blank:]]' /proc/self/mountinfo 
28 0 8:1 / / rw,relatime shared:1 - ext4 /dev/sda1 rw,data=ordered

単純なパターンのパターンは、出力で目的のデバイスに関する情報をすでに提供していますが、特定の文字列を1つだけ抽出するための追加のフィルタリングも可能です。


弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.