Como encontrar o driver (módulo) associado a um dispositivo no Linux?

50

No Linux, dado:

  • um dispositivo, por exemplo /dev/sda,
  • e seus números maiores e menores, por exemplo 8, 0,

como posso saber qual módulo / driver está "dirigindo" isso?

Posso cavar /sysou /procdescobrir isso?

Totor
fonte
Alguma combinação de lsmod, /proc/modulese modinfo?
4
stackoverflow.com/questions/2911050 parece o mesmo que esta pergunta.
22615 Michael Jackson
Totor, eu adicionei a recompensa porque outro usuário postou a mesma pergunta porque sentiu que este não havia recebido atenção suficiente. Pedi a ele para excluir sua pergunta e ofereci uma recompensa por essa para obter mais respostas. Lembre-se de aceitar uma das respostas abaixo se elas responderem à sua pergunta.
terdon
@terdon obrigado pela recompensa, produziu boas respostas. Ainda não testei tudo cuidadosamente, mas vou aceitar a resposta de Graeme enquanto isso.
30614 Totor

Respostas:

58

Para obter essas informações de sysfsum arquivo de dispositivo, primeiro determine o número principal / secundário observando a saída de ls -l, por exemplo

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

O 8, 0nos diz que o número principal é 8e o menor é 0. O bno início da listagem também nos diz que é um dispositivo de bloco. Outros dispositivos podem ter um cdispositivo para caracteres no início.

Se você olhar para baixo /sys/dev, verá dois diretórios. Um chamado blocke um chamado char. O acéfalo aqui é que estes são para dispositivos de blocos e caracteres, respectivamente. Cada dispositivo é então acessível por seu número maior / menor neste diretório. Se houver um driver disponível para o dispositivo, ele pode ser encontrado lendo o destino do driverlink neste ou no devicesubdiretório. Por exemplo, para o meu /dev/sdaeu posso simplesmente fazer:

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

Isso mostra que o sddriver é usado para o dispositivo. Se você não tiver certeza se o dispositivo é um dispositivo de bloco ou caractere, no shell, você pode simplesmente substituir esta peça por uma *. Isso funciona tão bem:

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

Os dispositivos de bloco também podem ser acessados ​​diretamente por meio de seus nomes, por meio de /sys/blockou /sys/class/block. Por exemplo:

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

Observe que a existência de vários diretórios /syspode mudar dependendo da configuração do kernel. Além disso, nem todos os dispositivos possuem uma devicesubpasta. Por exemplo, este é o caso de arquivos de dispositivos de partição como /dev/sda1. Aqui você precisa acessar o dispositivo para todo o disco (infelizmente não há syslinks para isso).

Uma coisa final que pode ser útil é listar os drivers de todos os dispositivos para os quais estão disponíveis. Para isso, você pode usar globs para selecionar todos os diretórios nos quais os links do driver estão presentes. Por exemplo:

$ 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

Finalmente, para divergir um pouco da questão, adicionarei outro /systruque global para obter uma perspectiva muito mais ampla sobre quais drivers estão sendo usados ​​por quais dispositivos (embora não necessariamente aqueles com um arquivo de dispositivo):

find /sys/bus/*/drivers/* -maxdepth 1 -lname '*devices*' -ls

Atualizar

Observando com mais atenção a saída de udevadm, ele parece funcionar encontrando o /sysdiretório canônico (como você obteria se referenciasse os diretórios principais / secundários acima) e, em seguida, subindo na árvore de diretórios, imprimindo as informações que encontrar. Dessa forma, você obtém informações sobre os dispositivos pai e todos os drivers que eles usam.

Para experimentar isso, escrevi o script abaixo para subir na árvore de diretórios e exibir informações em cada nível relevante. udevparece procurar arquivos legíveis em cada nível, com seus nomes e conteúdos incorporados ATTRS. Em vez de fazer isso, eu mostro o conteúdo dos ueventarquivos em cada nível (aparentemente a presença disso define um nível distinto em vez de apenas um subdiretório). Também mostro o nome base de todos os links do subsistema que encontro e isso mostra como o dispositivo se encaixa nessa hierarquia. udevadmnão exibe as mesmas informações, portanto, essa é uma boa ferramenta complementar. As informações do dispositivo pai (por exemplo, PCIinformações) também são úteis se você deseja corresponder a saída de outras ferramentas, como lshwdispositivos de nível superior.

#!/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
Graeme
fonte
Existe alguma maneira de determinar todos os drivers que estão sendo usados? Como por exemplo, a udevadmresposta lhe dará sde ahci. Existe uma maneira de determinar se ahciestá sendo usado também?
Patrick
@ Patrick, sim, atualizado.
Graeme
Ótima resposta, obrigado! Apenas para observar, no meu caso, o link estava device/device/, então meu readlinkcomando parecia readlink /sys/dev/char/XX\:Y/device/device/driver.
Harry Cutts
19

Você pode usar a udevadmferramenta para descobrir isso.
O comando seria udevadm info -a -n /dev/sdae, em seguida, observe os DRIVER==parâmetros.

# udevadm info -a -n /dev/sda | grep -oP 'DRIVERS?=="\K[^"]+'  
sd
ahci

Isso mostra que existem 2 drivers envolvidos no fornecimento deste dispositivo sde ahci. O primeiro, sdé diretamente responsável pelo /dev/sdadispositivo, mas usa o ahcidriver de acordo.

 

A saída do udevadmcomando se parece com isso e inclui uma descrição de como ele funciona.

# 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==""
Patrick
fonte
1
@ECarterYoung Onde você vê que udevadmé removido (ou até recomendado)? Eu não consigo encontrar nada, mesmo dando uma dica nisso.
Patrick
1
@ECarterYoung eu fiz, não vejo nada disso.
Patrick
Eu estava errado sobre a ausência do UEVENT_HELPER no kernel. Nos sistemas executando systemd, essa entrada está em branco, mas o helpr ainda está presente no sistema.
precisa saber é o seguinte
4

Use o comando hwinfo e modelo e driver de saída. Se não houver driver, ele não será mostrado. Por exemplo, para discos:

# hwinfo --block | grep -Ei "driver \: | modelo \:"
  Modelo: "Disquete"
  Modelo: "FUJITSU MHZ2080B"
  Driver: "ahci", "sd"
  Modelo: "Partição"
  Modelo: "Partição"
  Modelo: "Partição"
  Modelo: "Cartão múltiplo genérico"
  Driver: "ums-realtek", "sd"
  Modelo: "Realtek USB2.0-CRW"
  Driver: "ums-realtek"

Para placas de rede:

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

Para dispositivos USB:

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

Use hwinfo --help para descobrir quais outros tipos de dispositivos você pode consultar. O hwinfo é instalado por padrão, por exemplo, no SUSE Linux.

Thorsten Staerk
fonte
Para relacionar isso a um arquivo de dispositivo específico, uma maneira é adicionar a --onlyopção. Por exemplo hwinfo --block --only /dev/sda | grep ....
Graeme
3

lshwé uma ferramenta incrível para listar o hardware encontrado em sua máquina. Você precisará instalá-lo primeiro antes de executar.

$ yum install lshw
$ apt-get install lshw

Use yumou apt-getdependendo do sistema que você está usando. Em seguida, para listar especificamente o hardware de armazenamento:

# 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

Você pode executá-lo rootpara obter todas as informações de volta.

Caso contrário, você lspcitambém pode fornecer informações sobre o seu 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

Para descobrir o número principal e o menor de um dispositivo, basta executá ls-lo.

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

Nesta saída, o bin brw-rw----.significa que este é um dispositivo de bloco. Os dígitos 8e 0são, respectivamente, o número principal e o menor do dispositivo.

Spack
fonte
1
Minha pergunta é sobre encontrar o link entre um dispositivo e seu módulo / driver. Onde você responde isso?
precisa saber é o seguinte
1
@ Motor Nas duas saídas lshwe lspcivocê pode ver o módulo usado por um dispositivo: configuration: driver = ahci latency = 0 e o driver do Kernel em uso: ahci .
Spack