Per ottenere queste informazioni da sysfs
per un file di dispositivo, per prima cosa determina 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 è 0
. Il b
all'inizio del listato ci dice anche che si tratta di un dispositivo a blocchi. Altri dispositivi potrebbero avere un c
per dispositivo carattere 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 in questa directory. Se è disponibile un driver per il dispositivo, può essere trovato leggendo il target 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
Ciò dimostra che il file sd
driver viene utilizzato per il dispositivo. Se non sei sicuro che il dispositivo sia un dispositivo a blocchi oa caratteri, nella shell puoi semplicemente sostituire questa parte con un *
. Funziona altrettanto bene:
$ readlink /sys/dev/*/8\:0/device/driver
../../../../../../../bus/scsi/drivers/sd
È inoltre possibile accedere direttamente ai dispositivi a blocchi tramite il loro nome tramite /sys/block
o /sys/class/block
. Ad esempio:
$ readlink /sys/block/sda/device/driver
../../../../../../../bus/scsi/drivers/sd
Si noti 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 dei file del 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 dei driver. Ad esempio:
$ 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 discostarsi un po' dalla domanda, aggiungerò un altro /sys
glob per ottenere 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 /sys
canonico directory (come si otterrebbe se si dereferenziassero le directory principali/minori sopra), quindi risalendo l'albero delle directory, stampando tutte le informazioni che trova. In questo modo ottieni informazioni sui dispositivi dei genitori e anche sui driver che utilizzano.
Per sperimentare questo ho scritto lo script qui sotto per risalire l'albero delle directory e visualizzare le informazioni a ogni livello rilevante. udev
sembra cercare file leggibili ad ogni livello, con i loro nomi e contenuti incorporati in ATTRS
. Invece di fare questo, visualizzo il contenuto del 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 del sottosistema che trovo e questo mostra come il dispositivo si inserisce in questa gerarchia. udevadm
non visualizza le stesse informazioni, quindi questo è un ottimo strumento complementare. Le informazioni sul dispositivo principale (ad es. PCI
information) è 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
Puoi usare il udevadm
strumento per scoprirlo.
Il comando sarebbe udevadm info -a -n /dev/sda
, quindi guarda DRIVER==
parametri.
# udevadm info -a -n /dev/sda | grep -oP 'DRIVERS?=="\K[^"]+'
sd
ahci
Ciò dimostra che in realtà ci sono 2 driver coinvolti nella fornitura di questo dispositivo, sd
e ahci
. Il primo, sd
è direttamente responsabile del /dev/sda
dispositivo, ma utilizza il ahci
conducente sotto.
L'output del file udevadm
Il comando ha questo aspetto e include una descrizione di come funziona.
# udevadm info -a -n /dev/sda
Udevadm info starts with the device specified by the devpath and then
walks up the chain of parent devices. It prints for every device
found, all possible attributes in the udev rules key format.
A rule to match, can be composed by the attributes of the device
and the attributes from one single parent device.
looking at device '/devices/pci0000:00/0000:00:1f.2/ata1/host0/target0:0:0/0:0:0:0/block/sda':
KERNEL=="sda"
SUBSYSTEM=="block"
DRIVER==""
ATTR{ro}=="0"
ATTR{size}=="500118192"
ATTR{stat}==" 84786 1420 3091333 40215 966488 12528 14804028 2357668 0 1146934 2396653"
ATTR{range}=="16"
ATTR{discard_alignment}=="0"
ATTR{events}==""
ATTR{ext_range}=="256"
ATTR{events_poll_msecs}=="-1"
ATTR{alignment_offset}=="0"
ATTR{inflight}==" 0 0"
ATTR{removable}=="0"
ATTR{capability}=="50"
ATTR{events_async}==""
looking at parent device '/devices/pci0000:00/0000:00:1f.2/ata1/host0/target0:0:0/0:0:0:0':
KERNELS=="0:0:0:0"
SUBSYSTEMS=="scsi"
DRIVERS=="sd"
ATTRS{rev}=="VZJ4"
ATTRS{type}=="0"
ATTRS{scsi_level}=="6"
ATTRS{model}=="LITEONIT LMT-256"
ATTRS{state}=="running"
ATTRS{queue_type}=="simple"
ATTRS{iodone_cnt}=="0x10daad"
ATTRS{iorequest_cnt}=="0x10ead1"
ATTRS{queue_ramp_up_period}=="120000"
ATTRS{device_busy}=="0"
ATTRS{evt_capacity_change_reported}=="0"
ATTRS{timeout}=="30"
ATTRS{evt_media_change}=="0"
ATTRS{ioerr_cnt}=="0x2"
ATTRS{queue_depth}=="31"
ATTRS{vendor}=="ATA "
ATTRS{evt_soft_threshold_reached}=="0"
ATTRS{device_blocked}=="0"
ATTRS{evt_mode_parameter_change_reported}=="0"
ATTRS{evt_lun_change_reported}=="0"
ATTRS{evt_inquiry_change_reported}=="0"
ATTRS{iocounterbits}=="32"
ATTRS{eh_timeout}=="10"
looking at parent device '/devices/pci0000:00/0000:00:1f.2/ata1/host0/target0:0:0':
KERNELS=="target0:0:0"
SUBSYSTEMS=="scsi"
DRIVERS==""
looking at parent device '/devices/pci0000:00/0000:00:1f.2/ata1/host0':
KERNELS=="host0"
SUBSYSTEMS=="scsi"
DRIVERS==""
looking at parent device '/devices/pci0000:00/0000:00:1f.2/ata1':
KERNELS=="ata1"
SUBSYSTEMS==""
DRIVERS==""
looking at parent device '/devices/pci0000:00/0000:00:1f.2':
KERNELS=="0000:00:1f.2"
SUBSYSTEMS=="pci"
DRIVERS=="ahci"
ATTRS{irq}=="41"
ATTRS{subsystem_vendor}=="0x144d"
ATTRS{broken_parity_status}=="0"
ATTRS{class}=="0x010601"
ATTRS{enabled}=="1"
ATTRS{consistent_dma_mask_bits}=="64"
ATTRS{dma_mask_bits}=="64"
ATTRS{local_cpus}=="0f"
ATTRS{device}=="0x1e03"
ATTRS{msi_bus}==""
ATTRS{local_cpulist}=="0-3"
ATTRS{vendor}=="0x8086"
ATTRS{subsystem_device}=="0xc0d3"
ATTRS{numa_node}=="-1"
ATTRS{d3cold_allowed}=="1"
looking at parent device '/devices/pci0000:00':
KERNELS=="pci0000:00"
SUBSYSTEMS==""
DRIVERS==""
Utilizzare il comando hwinfo e il modello di output e il driver. Se non è presente alcun driver, non verrà visualizzato. Ad esempio per i dischi:
# hwinfo --block | grep -Ei "driver\:|model\:" Model: "Floppy Disk" Model: "FUJITSU MHZ2080B" Driver: "ahci", "sd" Model: "Partition" Model: "Partition" Model: "Partition" Model: "Generic Multi-Card" Driver: "ums-realtek", "sd" Model: "Realtek USB2.0-CRW" Driver: "ums-realtek"
Per le schede di rete:
# hwinfo --netcard | grep -Ei "driver\:|model\:" Model: "Broadcom NetXtreme BCM5764M Gigabit Ethernet PCIe" Driver: "tg3" Model: "Intel Wireless WiFi Link 5100" Driver: "iwlwifi"
Per dispositivi USB:
# hwinfo --usb | grep -Ei "driver\:|model\:" Model: "Linux 3.11.10-7-desktop uhci_hcd UHCI Host Controller" Driver: "hub" Model: "Linux 3.11.10-7-desktop uhci_hcd UHCI Host Controller" Driver: "hub" Model: "IDEACOM IDC 6680" Driver: "usbhid" [...]
Usa hwinfo --help per scoprire quali altri tipi di dispositivi puoi interrogare. hwinfo è installato per impostazione predefinita, ad es. su SUSE Linux.