Su Linux, dato:
- un dispositivo, ad esempio
/dev/sda
, - e i suoi numeri maggiori e minori, ad esempio
8, 0
,
come faccio a sapere quale modulo/driver lo sta “guidando”?
Posso approfondire /sys
o /proc
per scoprirlo?
Risposta accettata:
Per ottenere queste informazioni da sysfs
per un file di dispositivo, determina prima il numero maggiore/minore osservando l'output di ls -l
, ad esempio
$ ls -l /dev/sda
brw-rw---- 1 root disk 8, 0 Apr 17 12:26 /dev/sda
Il 8, 0
ci dice che il numero maggiore è 8
e il minore è . Il
b
all'inizio dell'elenco ci dice anche che si tratta di un dispositivo a blocchi. Altri dispositivi potrebbero avere un c
per il dispositivo del personaggio all'inizio.
Se poi guardi sotto /sys/dev
, vedrai che ci sono due directory. Uno chiamato block
e uno chiamato char
. Il gioco da ragazzi qui è che questi sono rispettivamente per dispositivi a blocchi e caratteri. Ogni dispositivo è quindi accessibile dal suo numero maggiore/minore è questa directory. Se è disponibile un driver per il dispositivo, è possibile trovarlo leggendo la destinazione del driver
link in questo o nel device
sottodirectory. Ad esempio, per il mio /dev/sda
Posso semplicemente fare:
$ readlink /sys/dev/block/8\:0/device/driver
../../../../../../../bus/scsi/drivers/sd
Questo mostra che il sd
driver viene utilizzato per il dispositivo. Se non sei sicuro che il dispositivo sia un dispositivo a blocchi o a caratteri, nella shell puoi semplicemente sostituire questa parte con un *
. Funziona altrettanto bene:
$ readlink /sys/dev/*/8\:0/device/driver
../../../../../../../bus/scsi/drivers/sd
È anche possibile accedere ai dispositivi a blocchi direttamente tramite il loro nome tramite /sys/block
o /sys/class/block
. Es.:
$ readlink /sys/block/sda/device/driver
../../../../../../../bus/scsi/drivers/sd
Nota che l'esistenza di varie directory in /sys
può cambiare a seconda della configurazione del kernel. Inoltre, non tutti i dispositivi hanno un device
sottocartella. Ad esempio, questo è il caso di file di dispositivo di partizione come /dev/sda1
. Qui devi accedere al dispositivo per l'intero disco (purtroppo non ci sono sys
link per questo).
Un'ultima cosa che può essere utile fare è elencare i driver per tutti i dispositivi per i quali sono disponibili. Per questo è possibile utilizzare i glob per selezionare tutte le directory in cui sono presenti i collegamenti del driver. Es.:
$ ls -l /sys/dev/*/*/device/driver && ls -l /sys/dev/*/*/driver
lrwxrwxrwx 1 root root 0 Apr 17 12:27 /sys/dev/block/11:0/device/driver -> ../../../../../../../bus/scsi/drivers/sr
lrwxrwxrwx 1 root root 0 Apr 17 12:26 /sys/dev/block/8:0/device/driver -> ../../../../../../../bus/scsi/drivers/sd
lrwxrwxrwx 1 root root 0 Apr 17 12:26 /sys/dev/block/8:16/device/driver -> ../../../../../../../bus/scsi/drivers/sd
lrwxrwxrwx 1 root root 0 Apr 17 12:26 /sys/dev/block/8:32/device/driver -> ../../../../../../../../../bus/scsi/drivers/sd
lrwxrwxrwx 1 root root 0 Apr 17 20:38 /sys/dev/char/189:0/driver -> ../../../../bus/usb/drivers/usb
lrwxrwxrwx 1 root root 0 Apr 17 20:38 /sys/dev/char/189:1024/driver -> ../../../../bus/usb/drivers/usb
lrwxrwxrwx 1 root root 0 Apr 17 20:38 /sys/dev/char/189:128/driver -> ../../../../bus/usb/drivers/usb
lrwxrwxrwx 1 root root 0 Apr 17 20:38 /sys/dev/char/189:256/driver -> ../../../../bus/usb/drivers/usb
lrwxrwxrwx 1 root root 0 Apr 17 20:38 /sys/dev/char/189:384/driver -> ../../../../bus/usb/drivers/usb
lrwxrwxrwx 1 root root 0 Apr 17 12:26 /sys/dev/char/189:512/driver -> ../../../../bus/usb/drivers/usb
lrwxrwxrwx 1 root root 0 Apr 17 12:26 /sys/dev/char/189:513/driver -> ../../../../../bus/usb/drivers/usb
lrwxrwxrwx 1 root root 0 Apr 17 12:26 /sys/dev/char/189:514/driver -> ../../../../../bus/usb/drivers/usb
lrwxrwxrwx 1 root root 0 Apr 17 12:26 /sys/dev/char/189:640/driver -> ../../../../bus/usb/drivers/usb
lrwxrwxrwx 1 root root 0 Apr 17 12:26 /sys/dev/char/189:643/driver -> ../../../../../bus/usb/drivers/usb
lrwxrwxrwx 1 root root 0 Apr 17 20:38 /sys/dev/char/189:768/driver -> ../../../../bus/usb/drivers/usb
lrwxrwxrwx 1 root root 0 Apr 17 20:38 /sys/dev/char/189:896/driver -> ../../../../bus/usb/drivers/usb
lrwxrwxrwx 1 root root 0 Apr 17 12:26 /sys/dev/char/21:0/device/driver -> ../../../../../../../bus/scsi/drivers/sd
lrwxrwxrwx 1 root root 0 Apr 17 12:26 /sys/dev/char/21:1/device/driver -> ../../../../../../../bus/scsi/drivers/sd
lrwxrwxrwx 1 root root 0 Apr 17 12:27 /sys/dev/char/21:2/device/driver -> ../../../../../../../bus/scsi/drivers/sr
lrwxrwxrwx 1 root root 0 Apr 17 12:26 /sys/dev/char/21:3/device/driver -> ../../../../../../../../../bus/scsi/drivers/sd
lrwxrwxrwx 1 root root 0 Apr 17 12:26 /sys/dev/char/250:0/device/driver -> ../../../../../../../bus/hid/drivers/hid-generic
lrwxrwxrwx 1 root root 0 Apr 17 12:26 /sys/dev/char/250:1/device/driver -> ../../../../../../../bus/hid/drivers/hid-generic
lrwxrwxrwx 1 root root 0 Apr 17 12:26 /sys/dev/char/250:2/device/driver -> ../../../../../../../bus/hid/drivers/hid-generic
lrwxrwxrwx 1 root root 0 Apr 17 12:26 /sys/dev/char/252:0/device/driver -> ../../../../../../../bus/scsi/drivers/sd
lrwxrwxrwx 1 root root 0 Apr 17 12:26 /sys/dev/char/252:1/device/driver -> ../../../../../../../bus/scsi/drivers/sd
lrwxrwxrwx 1 root root 0 Apr 17 12:27 /sys/dev/char/252:2/device/driver -> ../../../../../../../bus/scsi/drivers/sr
lrwxrwxrwx 1 root root 0 Apr 17 12:26 /sys/dev/char/252:3/device/driver -> ../../../../../../../../../bus/scsi/drivers/sd
lrwxrwxrwx 1 root root 0 Apr 17 19:53 /sys/dev/char/254:0/device/driver -> ../../../bus/pnp/drivers/rtc_cmos
lrwxrwxrwx 1 root root 0 Apr 17 19:53 /sys/dev/char/29:0/device/driver -> ../../../bus/platform/drivers/simple-framebuffer
lrwxrwxrwx 1 root root 0 Apr 17 19:53 /sys/dev/char/4:64/device/driver -> ../../../bus/pnp/drivers/serial
lrwxrwxrwx 1 root root 0 Apr 17 19:53 /sys/dev/char/4:65/device/driver -> ../../../bus/platform/drivers/serial8250
lrwxrwxrwx 1 root root 0 Apr 17 19:53 /sys/dev/char/4:66/device/driver -> ../../../bus/platform/drivers/serial8250
lrwxrwxrwx 1 root root 0 Apr 17 19:53 /sys/dev/char/4:67/device/driver -> ../../../bus/platform/drivers/serial8250
lrwxrwxrwx 1 root root 0 Apr 17 12:26 /sys/dev/char/6:0/device/driver -> ../../../bus/pnp/drivers/parport_pc
lrwxrwxrwx 1 root root 0 Apr 17 12:26 /sys/dev/char/99:0/device/driver -> ../../../bus/pnp/drivers/parport_pc
Infine, per discostarmi un po' dalla domanda, aggiungerò un altro /sys
trucco glob per avere una prospettiva molto più ampia su quali driver vengono utilizzati da quali dispositivi (anche se non necessariamente quelli con un file di dispositivo):
find /sys/bus/*/drivers/* -maxdepth 1 -lname '*devices*' -ls
Aggiorna
Osservando più da vicino l'output di udevadm
, sembra funzionare trovando il canonico /sys
directory (come si otterrebbe se si dereferenziasse le directory principali/minori sopra), quindi risalire l'albero delle directory, stampando tutte le informazioni che trova. In questo modo ottieni informazioni sui dispositivi principali e anche su eventuali driver che utilizzano.
Per sperimentare questo ho scritto lo script qui sotto per salire sull'albero delle directory e visualizzare le informazioni a ogni livello rilevante. udev
sembra cercare file leggibili a ogni livello, con i loro nomi e contenuti incorporati in ATTRS
. Invece di farlo visualizzo il contenuto di uevent
file a ogni livello (apparentemente la presenza di questo definisce un livello distinto piuttosto che solo una sottodirectory). Mostro anche il nome di base di tutti i collegamenti di sottosistema che trovo e questo mostra come il dispositivo si adatta a questa gerarchia. udevadm
non visualizza le stesse informazioni, quindi questo è un bel strumento complementare. Le informazioni sul dispositivo principale (ad es. PCI
informazioni) è utile anche se vuoi abbinare l'output di altri strumenti come lshw
a dispositivi di livello superiore.
#!/bin/bash
dev=$(readlink -m $1)
# test for block/character device
if [ -b "$dev" ]; then
mode=block
elif [ -c "$dev" ]; then
mode=char
else
echo "$dev is not a device file" >&2
exit 1
fi
# stat outputs major/minor in hex, convert to decimal
data=( $(stat -c '%t %T' $dev) ) || exit 2
major=$(( 0x${data[0]} ))
minor=$(( 0x${data[1]} ))
echo -e "Given device: $1"
echo -e "Canonical device: $dev"
echo -e "Major: $major"
echo -e "Minor: $minor\n"
# sometimes nodes have been created for devices that are not present
dir=$(readlink -f /sys/dev/$mode/$major\:$minor)
if ! [ -e "$dir" ]; then
echo "No /sys entry for $dev" >&2
exit 3
fi
# walk up the /sys hierarchy one directory at a time
# stop when there are three levels left
while [[ $dir == /*/*/* ]]; do
# it seems the directory is only of interest if there is a 'uevent' file
if [ -e "$dir/uevent" ]; then
echo "$dir:"
echo " Uevent:"
sed 's/^/ /' "$dir/uevent"
# check for subsystem link
if [ -d "$dir/subsystem" ]; then
subsystem=$(readlink -f "$dir/subsystem")
echo -e "\n Subsystem:\n ${subsystem##*/}"
fi
echo
fi
# strip a subdirectory
dir=${dir%/*}
done