Obtener nodo de dispositivo por par de números mayor / menor


12

Cada nodo de dispositivo debajo /devtiene su propio par de números mayor / menor. Sé que podemos recuperar este par de números del nodo del dispositivo mediante stat, de esta manera:

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

O, ls -ltambién muestra estos números.

Pero, ¿cómo podemos obtener nodo (s) de dispositivo por números mayores y menores dados? La única forma en que soy consciente es algún tipo de truco ls -l+ awk, pero realmente espero que haya una mejor solución.


@mikeserv, sí, sé que algunos dispositivos pueden compartir estos números, así que en mi pregunta inicial mencioné: "obtener nodo (s) de dispositivo". Idealmente, quiero obtener una lista con todos los nodos del dispositivo cuyos números mayores / menores coincidan, un nodo por línea. Es extraño que no tengamos una herramienta lista para eso. Gracias por la respuesta por cierto!
Dmitry Frank el

Respuestas:


7

Encontré un enfoque más simple usando el sys pseudofilesystem, en / sys / dev tiene los dispositivos ordenados por tipo y luego por mayor / menor, el archivo uevent contiene el nombre del dispositivo y un montón de otra información.

Así por ejemplo,

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

Ecos

loop0
vcs

Nota: Esto fue probado en Debian Wheezy


para encontrar hacia atrás desde el nombre del desarrollador:for file in $(ls /sys/dev/block/ ); do source /sys/dev/block/${file}/uevent; if [ "$DEVNAME" == "sda1" ] ; then echo ${file}; fi done;
BBK

5

No estoy seguro de lo que quieres decir.

mknod foo b 8 0

Creará el archivo del dispositivo llamado foocomo un dispositivo de bloque con mayor 8 y menor 0. Si quiere encontrar uno o cualquiera de los archivos /devque tienen el mismo tipo, mayor y menor, puede hacer (con zsh):

  • Para dispositivo de bloque 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
    
  • para 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
    

Tenga en cuenta que cualquier cosa puede crear archivos /dev. En los viejos tiempos, era un script que creaba archivos estáticos allí. En algún momento, incluso tenías un sistema de archivos especial a la /proc.

En las versiones modernas de Linux, generalmente se udevbasa en la entrada del núcleo.

El nombre que elige para el archivo del dispositivo base se basa en el DEVNAMEproporcionado por el núcleo. udevlas reglas pueden cambiar eso, pero generalmente no lo hacen, y algunas udevreglas agregarán algunos enlaces simbólicos más por conveniencia (como los que /dev/disk/by...están).

Puede ir de mayor: menor a kernel DEVNAMEmirando:

$ 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

También puede obtener esa información de la udevbase de datos como lo ha demostrado mikeserv.


5

Aparentemente se puede hacer de manera más simple udevadm, y acabo de descubrir cómo.

Para obtener el DEVNAMEde udevadmSolo hay que hacer:

udevadm info -rq name $PATH

Por ejemplo, si quisieras saber el /devnombre /sys/dev/char/5:1que harías:

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

SALIDA

/dev/console

La -ropción es especificar una --rootruta ed; sin ella, el resultado anterior sería de solo lectura console. La -qopción especifica una base de datos --queryy toma el operando nameaquí, porque queremos el DEVNAME.

Una forma muy simple de encontrar la ruta a un dispositivo de bloqueo y / o carácter dado solo el mayor: los números menores podrían verse así:

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

Entonces corriendo:

mmdev 8 0

huellas dactilares...

b:8:0:/dev/sda

Aquí está el primero que escribí.

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

Esto solo escanea la udevadm info --export-dbsalida para los números coincidentes. El resultado se ve así:

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

El flujo de trabajo es como:

  • intente quitar la [^=]*DEVNAME=cuerda del encabezado de cada línea

  • si una línea no tiene un primer carácter o su primer carácter es /copiar esa línea sobre el hespacio antiguo

  • Si una línea coincide, MAJOR=anexe Nla línea de entrada ext al espacio del patrón

  • si hay 2 líneas en el espacio del patrón que coinciden =$1\n.*=$2$, copie el hespacio anterior sobre el espacio del patrón y autoimprima; de lo contrario, elimine el espacio del patrón

Entonces si lo hago:

majminpath 7 133 ; majminpath 8 0 ; majminpath 8 1

SALIDA

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

Pero, como señala @xae, los dispositivos de tipo block / char pueden compartir combinaciones maj: min, por lo que esto podría imprimir más de una ruta por llamada.


1
Desafortunadamente, no es tan fácil, un bloque y un dispositivo de caracteres pueden compartir el mismo número principal. Echa un vistazo al archivo / proc / devices.
xae

Tengo que verificar el subsistema, eso es correcto. Gracias, @xae.
mikeserv

1

Por desgracia , la /sys/devjerarquía solo se agregó al kernel tan tarde como 2.6.27 ( cf. la confirmación relevante contra la base de código del kernel), por lo que necesitamos un enfoque "bifurcado".

Sea $My $m, respectivamente, el número mayor y menor de nuestro archivo de dispositivo.

Publicar 2.6.27 núcleos

Según lo sugerido por otros, el enfoque más simple libera el poder del sysfssistema de archivos "virtual", persiguiendo directamente los archivos nombrados $M:$men la carpeta /sys/dev(es de esperar más de un archivo si no sabemos si nuestro dispositivo es un personaje) o uno basado en bloques), y luego obtener el ueventarchivo (en un subshell para evitar la contaminación del espacio de nombres):

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

Pre 2.6.27 núcleos

Supongamos, por simplicidad, que nuestro archivo es un dispositivo de bloque (se aplica un enfoque similar para los dispositivos de caracteres). Buscaremos la cadena en $M:$mtoda la /sys/blockjerarquía, examinando (debajo de esa carpeta) el contenido de cada archivo cuyo nombre sea dev. Si /sys/block/<...>/<DEV>/deves uno de esos archivos, entonces DEVestá obligado a ser el nombre de nuestro dispositivo:

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

0

En Linux es posible aprovechar ciertos archivos en /procel sistema de archivos 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

La forma simple del patrón ya proporciona información sobre el dispositivo deseado en la salida, sin embargo, también es posible el filtrado adicional para extraer solo una cadena en particular.


Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.