Dapatkan simpul perangkat dengan pasangan nomor besar / kecil

12

Setiap simpul perangkat di bawah /devmemiliki pasangan nomor mayor / minornya sendiri. Saya tahu bahwa kami dapat mengambil pasangan angka ini dari simpul perangkat dengan cara stat, seperti ini:

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

Atau, ls -ljuga menunjukkan angka-angka ini.

Tapi bagaimana kita bisa mendapatkan node perangkat dengan angka besar dan kecil? Satu-satunya cara saya sadar adalah semacam ls -l+ awktrik, tapi saya sangat berharap ada solusi yang lebih baik.

Dmitry Frank
sumber
@ mikeserv, ya saya tahu bahwa beberapa perangkat dapat berbagi angka-angka ini, jadi dalam pertanyaan awal saya sebutkan: "get node device (s)". Idealnya saya ingin mendapatkan daftar dengan semua perangkat node yang cocok dengan nomor utama / minor, satu node per baris. Itu aneh kami tidak memiliki alat yang siap untuk itu. Terima kasih atas jawabannya btw!
Dmitry Frank

Jawaban:

7

Saya menemukan pendekatan yang lebih sederhana dengan menggunakan sistem pseudofiles sys , di / sys / dev Anda memiliki perangkat yang dipesan berdasarkan jenis lalu oleh may / minor, file uevent berisi nama perangkat dan banyak info lainnya.

Jadi misalnya,

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

Gema,

loop0
vcs

Catatan: Ini diuji dalam Debian Wheezy

xae
sumber
untuk menemukan mundur dari nama dev:for file in $(ls /sys/dev/block/ ); do source /sys/dev/block/${file}/uevent; if [ "$DEVNAME" == "sda1" ] ; then echo ${file}; fi done;
BBK
5

Tidak yakin apa yang kamu maksud.

mknod foo b 8 0

Akan membuat file perangkat yang disebut foosebagai perangkat blok dengan mayor 8 dan minor 0. Jika Anda bermaksud menemukan satu atau salah satu file di /devyang memiliki tipe yang sama, mayor dan minor, Anda dapat melakukan (dengan zsh):

  • Untuk perangkat blok 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
    
  • untuk perangkat 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
    

Perhatikan bahwa apa pun dapat membuat file /dev. Di masa lalu, itu adalah skrip yang membuat file statis di sana. Pada titik tertentu, Anda bahkan memiliki sistem file khusus à la /proc.

Pada versi Linux modern, biasanya udevdidasarkan pada input dari kernel.

Nama yang dipilih untuk file perangkat dasar didasarkan pada yang DEVNAMEdisediakan oleh kernel. udevaturan dapat mengubah itu tetapi umumnya tidak, dan beberapa udevaturan akan menambahkan lebih banyak symlink untuk kenyamanan (seperti yang /dev/disk/by...ada).

Anda dapat beralih dari mayor: minor ke kernel DEVNAMEdengan melihat:

$ 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

Anda juga bisa mendapatkan informasi itu dari udevdatabase seperti yang ditunjukkan mikeserv.

Stéphane Chazelas
sumber
5

Ternyata itu bisa dilakukan lebih sederhana dengan udevadm, dan saya baru tahu caranya.

Untuk mendapatkan DEVNAMEdari yang udevadmAnda butuhkan hanya lakukan:

udevadm info -rq name $PATH

Misalnya, jika Anda ingin tahu /devnama /sys/dev/char/5:1yang akan Anda lakukan:

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

KELUARAN

/dev/console

The -rpilihan adalah untuk menentukan --rootjalur ed - tanpa itu hasilnya di atas akan hanya membaca console. The -qpilihan menentukan database --querydan dibutuhkan operan namedi sini - karena kami ingin DEVNAME.

Cara yang sangat sederhana untuk menemukan jalur ke perangkat arang dan / atau blok yang hanya diberi nilai mayor: minor mungkin terlihat seperti:

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

Jadi berlari:

mmdev 8 0

cetakan ...

b:8:0:/dev/sda

Ini yang pertama saya tulis.

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

Ini hanya memindai udevadm info --export-dboutput untuk nomor yang cocok. Outputnya terlihat seperti:

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

Alur kerjanya seperti:

  • mencoba untuk mengupas [^=]*DEVNAME=string dari kepala setiap baris

  • jika suatu garis tidak memiliki karakter pertama atau karakter pertamanya adalah /salin garis itu di atas hruang lama

  • jika suatu baris cocok MAJOR=tambahkan Nbaris input ekst ke ruang pola

  • jika ada 2 garis dalam ruang pola yang cocok =$1\n.*=$2$maka salin hruang lama di atas ruang pola dan cetak-otomatis; lain menghapus ruang pola

Jadi jika saya lakukan:

majminpath 7 133 ; majminpath 8 0 ; majminpath 8 1

KELUARAN

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

Tetapi, seperti yang ditunjukkan oleh @xae, perangkat tipe blok / char dapat berbagi kombinasi maj: min, dan karenanya ini mungkin mencetak lebih dari satu jalur per panggilan.

mikeserv
sumber
1
Sayangnya itu tidak begitu mudah, sebuah blok dan perangkat karakter dapat berbagi nomor utama yang sama. Lihatlah file / proc / devices.
xae
Saya harus memeriksa subsistem - itu benar. Terima kasih, @xae.
mikeserv
1

Sayangnya , /sys/devhierachy hanya ditambahkan ke kernel selambat-lambatnya 2.6.27 ( lih. Komit terkait terhadap basis kode kernel), jadi kita membutuhkan pendekatan "bifurcated".

Biarkan $Mdan $m, masing-masing, menjadi nomor utama dan kecil dari file perangkat kami.

Posting 2.6.27 kernel

Seperti yang disarankan oleh orang lain, pendekatan paling sederhana melepaskan kekuatan dari sysfssistem file "virtual", dengan mengejar langsung untuk file yang dinamai di $M:$mbawah folder /sys/dev(lebih dari satu file diharapkan jika kita tidak tahu apakah perangkat kita adalah karakter- atau yang berbasis blok), dan kemudian sumber ueventfile (dalam subkulit untuk mencegah polusi namespace):

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

Pra 2.6.27 kernel

Mari kita asumsikan, demi kesederhanaan, bahwa file kita adalah perangkat blok (pendekatan serupa berlaku untuk perangkat karakter). Kami akan mencari string di $M:$mseluruh /sys/blockhierarki, dengan memeriksa (di bawah folder itu) konten dari setiap file yang namanya kebetulan dev. Jika /sys/block/<...>/<DEV>/devsalah satu file tersebut, maka DEVitu pasti nama perangkat kami:

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

Di Linux dimungkinkan untuk mengambil keuntungan dari file-file tertentu dalam /procsistem file virtual.

$ 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

Bentuk sederhana dari pola sudah memberikan informasi tentang perangkat yang diinginkan dalam output, namun pemfilteran tambahan untuk mengekstrak hanya satu string tertentu juga dimungkinkan.

Sergiy Kolodyazhnyy
sumber
0

Ada fungsi perpustakaan: makedev()

#include <sys/sysmacros.h>
dev_t makedev(unsigned int maj, unsigned int min);

Diberikan ID perangkat utama dan kecil, makedev () menggabungkan ini untuk menghasilkan ID perangkat, dikembalikan sebagai hasil fungsi.

Untuk detail lebih lanjut kunjungi: http://man7.org/linux/man-pages/man3/major.3.html

Krishna Kanth Yenumula
sumber