Come trovare il driver (modulo) associato a un dispositivo su Linux?


50

Su Linux, dato:

  • un dispositivo, ad esempio /dev/sda,
  • e i suoi numeri maggiori e minori, ad esempio 8, 0,

come posso sapere quale modulo / driver lo sta "guidando"?

Posso scavare /syso /procscoprirlo?


Alcuni combinazione di lsmod, /proc/modulese modinfo?

4
stackoverflow.com/questions/2911050 ha lo stesso aspetto di questa domanda.
Michael Tomkins,


Totor, ho aggiunto la generosità perché un altro utente ha pubblicato la stessa domanda perché sentiva che questa non aveva ricevuto abbastanza attenzione. Gli ho chiesto di eliminare la sua domanda e ho offerto una taglia su questo per ottenere più risposte. Ricordati di accettare una delle risposte seguenti se rispondono alla tua domanda.
terdon

@terdon grazie per la generosità, ha prodotto belle risposte. Non ho ancora testato attentamente tutto, ma intanto accetterò la risposta di Graeme .
Totor

Risposte:


58

Per ottenere queste informazioni da sysfsun file del dispositivo, determinare innanzitutto il numero maggiore / minore osservando l'output di ls -l, ad es

 $ ls -l /dev/sda
 brw-rw---- 1 root disk 8, 0 Apr 17 12:26 /dev/sda

Il 8, 0ci dice che il numero principale è 8e il minore è 0. bL'all'inizio della lista ci dice anche che si tratta di un dispositivo a blocchi. Altri dispositivi potrebbero avere un cdispositivo per i personaggi all'inizio.

Se poi guardi sotto /sys/dev, vedrai che ci sono due directory. Uno chiamato blocke uno chiamato char. Il gioco da ragazzi qui è che questi sono rispettivamente per dispositivi a blocchi e personaggi. Ogni dispositivo è quindi accessibile dal suo numero maggiore / minore è questa directory. Se è disponibile un driver per il dispositivo, è possibile trovarlo leggendo la destinazione del drivercollegamento in questa o nella devicesottodirectory. Ad esempio, per il mio /dev/sdaposso semplicemente fare:

$ readlink /sys/dev/block/8\:0/device/driver
../../../../../../../bus/scsi/drivers/sd

Ciò dimostra che il sddriver è utilizzato per il dispositivo. Se non si è sicuri che il dispositivo sia un dispositivo a blocchi o di caratteri, nella shell è possibile semplicemente sostituire questa parte con a *. Funziona altrettanto bene:

$ readlink /sys/dev/*/8\:0/device/driver
../../../../../../../bus/scsi/drivers/sd

Ai dispositivi a blocchi è inoltre possibile accedere direttamente tramite il loro nome tramite /sys/blocko /sys/class/block. Per esempio:

$ readlink /sys/block/sda/device/driver
../../../../../../../bus/scsi/drivers/sd

Si noti che l'esistenza di varie directory in /syspuò cambiare a seconda della configurazione del kernel. Inoltre, non tutti i dispositivi hanno una devicesottocartella. Ad esempio, questo è il caso di file di dispositivi di partizione come /dev/sda1. Qui devi accedere al dispositivo per l'intero disco (purtroppo non ci sono syscollegamenti 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 globs per selezionare tutte le directory in cui sono presenti i collegamenti del driver. Per esempio:

$ ls -l /sys/dev/*/*/device/driver ls -l /sys/dev/*/*/driver 
ls: cannot access ls: No such file or directory
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 divergere un po 'dalla domanda, aggiungerò un altro /systrucco globale 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

Aggiornare

Osservando più da vicino l'output di udevadm, sembra funzionare trovando la /sysdirectory canonica (come si otterrebbe se si dereferenziassero le directory maggiori / minori sopra), quindi risalendo la struttura della directory, stampando tutte le informazioni che trova. In questo modo puoi ottenere informazioni sui dispositivi genitori e su tutti i driver che usano.

Per sperimentare questo ho scritto lo script qui sotto per camminare sull'albero delle directory e visualizzare informazioni ad ogni livello rilevante. udevsembra cercare file leggibili ad ogni livello, con i loro nomi e contenuti incorporati ATTRS. Invece di farlo, visualizzo il contenuto dei ueventfile ad ogni livello (apparentemente la presenza di questo definisce un livello distinto anziché solo una sottodirectory). Mostro anche il nome di base di tutti i collegamenti del sottosistema che trovo e questo mostra come il dispositivo si adatta a questa gerarchia. udevadmnon visualizza le stesse informazioni, quindi questo è un bel strumento complementare. Le informazioni sul dispositivo genitore (ad es. PCIInformazioni) sono utili anche se si desidera abbinare l'output di altri strumenti come lshwdispositivi 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

Esiste un modo per determinare tutti i driver utilizzati? Come ad esempio la udevadmrisposta ti darà sde ahci. C'è un modo per determinare che ahciviene utilizzato anche?
Patrick,

@Patrick, sì, aggiornato.
Graeme,

Ottima risposta, grazie! Solo per notare, nel mio caso il collegamento era in device/device/, quindi il mio readlinkcomando sembrava readlink /sys/dev/char/XX\:Y/device/device/driver.
Harry Cutts,

19

Puoi usare lo udevadmstrumento per scoprirlo.
Il comando sarebbe udevadm info -a -n /dev/sdae quindi guardare i 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 sde ahci. Il primo sdè direttamente responsabile del /dev/sdadispositivo, ma utilizza il ahcidriver sottostante.

 

L'output del udevadmcomando è simile al seguente 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==""

1
@ECarterYoung Dove vedi che udevadmè stato rimosso (o addirittura consigliato)? Non riesco a trovare nulla nemmeno dandogli un suggerimento.
Patrick,

1
@ECarterYoung l'ho fatto, non vedo nulla del genere.
Patrick,

Mi sono sbagliato sull'assenza di UEVENT_HELPER nel kernel. Sui sistemi che eseguono systemd, questa voce è vuota, ma l'helpr è ancora presente sul sistema.
eyoung100,

4

Utilizzare il comando hwinfo e il modello e il driver di output. Se non è presente alcun driver, questo non verrà visualizzato. Ad esempio per i dischi:

# hwinfo --block | grep -Ei "driver \: | model \:"
  Modello: "Floppy Disk"
  Modello: "FUJITSU MHZ2080B"
  Driver: "ahci", "sd"
  Modello: "Partizione"
  Modello: "Partizione"
  Modello: "Partizione"
  Modello: "Multi-Card generica"
  Driver: "ums-realtek", "sd"
  Modello: "Realtek USB2.0-CRW"
  Driver: "ums-realtek"

Per le schede di rete:

# hwinfo --netcard | grep -Ei "driver \: | model \:"
  Modello: "Broadcom NetXtreme BCM5764M Gigabit Ethernet PCIe"
  Driver: "tg3"
  Modello: "Intel Wireless WiFi Link 5100"
  Driver: "iwlwifi"

Per i dispositivi USB:

# hwinfo --usb | grep -Ei "driver \: | model \:"
  Modello: "Linux 3.11.10-7-desktop uhci_hcd Controller host UHCI"
  Driver: "hub"
  Modello: "Linux 3.11.10-7-desktop uhci_hcd Controller host UHCI"
  Driver: "hub"
  Modello: "IDEACOM IDC 6680"
  Driver: "usbhid"
  [...]

Usa hwinfo --help per scoprire quali altri tipi di dispositivi puoi interrogare. hwinfo è installato di default, ad es. su SUSE Linux.


Per collegare questo a un determinato file di dispositivo, un modo è aggiungere l' --onlyopzione. Es hwinfo --block --only /dev/sda | grep ....
Graeme,

3

lshwè uno strumento fantastico per elencare l'hardware trovato nel tuo computer. Dovrai installarlo prima di eseguire.

$ yum install lshw
$ apt-get install lshw

Utilizzare yumo in apt-getbase al sistema in uso. Quindi per elencare in modo specifico l'hardware di archiviazione:

# lshw -class storage 
*-storage               
   description: SATA controller
   product: 5 Series/3400 Series Chipset 4 port SATA AHCI Controller
   vendor: Intel Corporation
   physical id: 1f.2
   bus info: pci@0000:00:1f.2
   version: 06
   width: 32 bits
   clock: 66MHz
   capabilities: storage msi pm ahci_1.0 bus_master cap_list
   configuration: driver=ahci latency=0
   resources: irq:41 ioport:1830(size=8) ioport:1824(size=4) ioport:1828(size=8) ioport:1820(size=4) ioport:1800(size=32) memory:f0305000-f03057ff

Potrebbe essere necessario eseguirlo rootper recuperare tutte le informazioni.

Altrimenti, lspcipuoi anche fornire informazioni sul tuo hardware:

$ lspci -vv
00:1f.2 SATA controller: Intel Corporation 5 Series/3400 Series Chipset 4 port SATA AHCI Controller (rev 06) (prog-if 01 [AHCI 1.0])
    Subsystem: Dell Device 0434
    Control: I/O+ Mem+ BusMaster+ SpecCycle- MemWINV- VGASnoop- ParErr- Stepping- SERR- FastB2B- DisINTx+
    Status: Cap+ 66MHz+ UDF- FastB2B+ ParErr- DEVSEL=medium >TAbort- <TAbort- <MAbort- >SERR- <PERR- INTx-
    Latency: 0
    Interrupt: pin B routed to IRQ 41
    Region 0: I/O ports at 1830 [size=8]
    Region 1: I/O ports at 1824 [size=4]
    Region 2: I/O ports at 1828 [size=8]
    Region 3: I/O ports at 1820 [size=4]
    Region 4: I/O ports at 1800 [size=32]
    Region 5: Memory at f0305000 (32-bit, non-prefetchable) [size=2K]
    Capabilities: <access denied>
    Kernel driver in use: ahci

Per scoprire il numero maggiore e minore di un dispositivo, basta eseguirlo ls.

$ ls -l /dev/sda
brw-rw----. 1 root disk 8, 0 13 avril 10:54 /dev/sda

In questa uscita, bin brw-rw----.significa che si tratta di un dispositivo a blocchi. Le cifre 8e 0sono rispettivamente il numero maggiore e minore del dispositivo.


1
La mia domanda riguarda la ricerca del collegamento tra un dispositivo e il suo modulo / driver. Dove rispondi a questo?
Totor

1
@Totor In entrambi l'output di lshwe lspcipuoi vedere il modulo utilizzato da un dispositivo: configurazione: driver = ahci latency = 0 e driver del kernel in uso: ahci .
Spacca il
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.