Ottieni il nodo del dispositivo per coppia di numeri maggiori / minori


12

Ogni nodo del dispositivo in /devha la propria coppia di numeri maggiore / minore. So che possiamo recuperare questa coppia di numeri dal nodo del dispositivo tramite stat, in questo modo:

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

Oppure ls -lmostra anche questi numeri.

Ma come possiamo ottenere i nodi del dispositivo in base a numeri maggiori e minori? L'unico modo in cui sono a conoscenza è una sorta di ls -l+ awktrucco, ma spero davvero che ci sia una soluzione migliore.


@mikeserv, sì, so che alcuni dispositivi possono condividere questi numeri, quindi nella mia domanda iniziale ho menzionato: "ottieni i nodi del dispositivo". Idealmente, voglio ottenere un elenco con tutti i nodi del dispositivo i cui numeri maggiori / minori corrispondono, un nodo per riga. È strano che non abbiamo uno strumento pronto per quello. Grazie per la risposta tra l'altro!
Dmitry Frank,

Risposte:


7

Ho trovato un approccio più semplice usando lo sse pseudofilesystem, su / sys / dev hai i dispositivi ordinati per tipo e poi per maggiore / minore, il file uevent contiene il nome del dispositivo e un sacco di altre informazioni.

Quindi per esempio,

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

Echoes,

loop0
vcs

Nota: questo è stato testato in Debian Wheezy


per trovare indietro dal nome dello sviluppatore:for file in $(ls /sys/dev/block/ ); do source /sys/dev/block/${file}/uevent; if [ "$DEVNAME" == "sda1" ] ; then echo ${file}; fi done;
BBK

5

Non sono sicuro cosa intendi.

mknod foo b 8 0

Creerà il file del dispositivo chiamato foocome dispositivo a blocchi con maggiore 8 e minore 0. Se intendi trovare uno o più file /devcon lo stesso tipo, maggiore e minore, puoi farlo (con zsh):

  • Per dispositivo a blocchi 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
    
  • per dispositivo 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
    

Si noti che qualsiasi cosa può creare file in /dev. Ai vecchi tempi, era uno script che creava file statici lì dentro. Ad un certo punto, hai persino avuto un file system speciale à la /proc.

Nelle versioni moderne di Linux, di solito si udevbasa sull'input del kernel.

Il nome che sceglie per il file del dispositivo di base si basa su quello DEVNAMEfornito dal kernel. udevle regole possono cambiarlo, ma generalmente no, e alcune udevregole aggiungeranno altri symlink per comodità (come /dev/disk/by...quelli).

Puoi passare da major: minor a kernel DEVNAMEguardando:

$ 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

È inoltre possibile ottenere tali informazioni dal udevdatabase come mostrato da mikeserv.


5

Apparentemente può essere fatto più semplicemente con udevadm, e ho appena scoperto come.

Per ottenere il DEVNAMEda udevadmdevi solo fare:

udevadm info -rq name $PATH

Ad esempio, se volessi sapere il /devnome per quello /sys/dev/char/5:1che dovresti fare:

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

PRODUZIONE

/dev/console

L' -ropzione è specificare un --rootpercorso ed - senza di esso il risultato sopra sarebbe di sola lettura console. L' -qopzione specifica un database --querye prende l'operando namequi - perché vogliamo DEVNAME.

Un modo molto semplice per trovare il percorso di un dispositivo char e / o block dato solo il maggiore: i numeri minori potrebbero apparire come:

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

Quindi in esecuzione:

mmdev 8 0

stampe ...

b:8:0:/dev/sda

Ecco il primo che ho scritto.

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

Questo scansiona solo l' udevadm info --export-dboutput per i numeri corrispondenti. L'output è simile a:

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

Il flusso di lavoro è simile a:

  • tenta di rimuovere la [^=]*DEVNAME=stringa dalla testa di ogni riga

  • se una riga non ha un primo carattere o il suo primo carattere è /copiarla su huno spazio vecchio

  • se una riga corrisponde alla MAJOR=riga di Ninput ext ext allo spazio del pattern

  • se ci sono 2 linee nello spazio del motivo che corrispondono, =$1\n.*=$2$quindi copia il hvecchio spazio sopra lo spazio del modello e stampa automatica; altrimenti elimina lo spazio modello

Quindi se lo faccio:

majminpath 7 133 ; majminpath 8 0 ; majminpath 8 1

PRODUZIONE

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

Ma, come sottolinea @xae, i dispositivi di tipo block / char possono condividere combinazioni maj: min, e quindi questo potrebbe probabilmente stampare più di un percorso per chiamata.


1
Sfortunatamente non è così facile, un blocco e un dispositivo personaggio possono condividere lo stesso numero maggiore. Dai un'occhiata al file / proc / devices.
xae,

Devo controllare il sottosistema - esatto. Grazie @xae.
Mikeserv,

1

Purtroppo , la /sys/devgerarchia è stata aggiunta al kernel solo fino al 2.6.27 ( cfr. Il commit pertinente contro la base di codice del kernel), quindi abbiamo bisogno di un approccio "biforcato".

Sia $Me $m, rispettivamente, il numero maggiore e minore del nostro file del dispositivo.

Posta 2.6.27 kernel

Come suggerito da altri, l'approccio più semplice scatena la potenza del sysfsfile system "virtuale", inseguendo direttamente i file denominati $M:$mnella cartella /sys/dev(ci si aspetta più di un file se non sappiamo se il nostro dispositivo è un personaggio- o uno basato su blocchi) e quindi il sourcing del ueventfile (in una subshell in modo da prevenire l'inquinamento dello spazio dei nomi):

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

Pre 2.6.27 kernel

Supponiamo, per semplicità, che il nostro file sia un dispositivo a blocchi (un approccio simile si applica ai dispositivi a caratteri). Cercheremo la stringa in $M:$mtutta la /sys/blockgerarchia, esaminando (sotto quella cartella) il contenuto di ogni file il cui nome sembra essere dev. Se /sys/block/<...>/<DEV>/devesiste uno di questi file, allora DEVè destinato a essere il nome del nostro dispositivo:

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

0

Su Linux è possibile sfruttare alcuni file nel /procfilesystem virtuale.

$ 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

La forma semplice del modello fornisce già informazioni sul dispositivo desiderato nell'output, tuttavia è possibile anche un filtro aggiuntivo per estrarre solo una stringa particolare.


Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.