Comment trouver le pilote (module) associé à un périphérique sous Linux?

50

Sous Linux, étant donné:

  • un appareil, par exemple /dev/sda,
  • et ses nombres majeurs et mineurs, par exemple 8, 0,

Comment puis-je savoir quel module / pilote le "conduit"?

Puis-je creuser /sysou /procdécouvrir cela?

Totor
la source
Une combinaison de lsmod, /proc/moduleset modinfo?
4
stackoverflow.com/questions/2911050 a le même aspect que cette question.
Michael Tomkins
Totor, j'ai ajouté la prime parce qu'un autre utilisateur a posé la même question car il estimait que celle-ci n'avait pas reçu suffisamment d'attention. Je lui ai demandé de supprimer sa question et lui ai offert une prime pour obtenir plus de réponses. N'oubliez pas d'accepter l'une des réponses ci-dessous si elles répondent à votre question.
terdon
@terdon merci pour la prime, cela a donné de bonnes réponses. Je n'ai pas encore tout testé avec soin, mais j'accepterai la réponse de Graeme d'ici là.
Totor

Réponses:

58

Pour obtenir ces informations sysfspour un fichier de périphérique, déterminez d’abord le numéro majeur / mineur en examinant le résultat ls -l, par exemple:

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

Le 8, 0nous dit que le numéro majeur est 8et le mineur est 0. Au bdébut de la liste, il est également indiqué que le périphérique est bloqué. D'autres appareils peuvent avoir un cappareil pour personnage au début.

Si vous regardez ensuite sous /sys/dev, vous verrez qu'il y a deux répertoires. Un appelé blocket un appelé char. Il va sans dire que ceux-ci sont destinés aux blocs et aux caractères, respectivement. Chaque appareil est alors accessible par son numéro majeur / mineur est ce répertoire. Si un pilote est disponible pour le périphérique, vous pouvez le trouver en lisant la cible du driverlien dans ce devicesous-répertoire. Par exemple, pour mon /dev/sdaje peux simplement faire:

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

Cela montre que le sdpilote est utilisé pour le périphérique. Si vous ne savez pas si le périphérique est un périphérique de type bloc ou caractère, vous pouvez simplement remplacer cette partie par un *. Cela fonctionne aussi bien:

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

Les appareils bloqués sont également accessibles directement via leur nom via /sys/blockou /sys/class/block. Par exemple:

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

Notez que l'existence de divers répertoires dans /syspeut changer en fonction de la configuration du noyau. De plus, tous les périphériques n’ont pas de devicesous - dossier. C'est le cas, par exemple, des fichiers de périphériques de partition /dev/sda1. Ici, vous devez accéder à l'appareil pour le disque entier (malheureusement, il n'y a pas de sysliens pour cela).

Une dernière chose qu'il peut être utile de faire est de répertorier les pilotes de tous les périphériques pour lesquels ils sont disponibles. Pour cela, vous pouvez utiliser globs pour sélectionner tous les répertoires dans lesquels les liens de pilotes sont présents. Par exemple:

$ 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

Enfin, pour s'écarter un peu de la question, je vais ajouter une autre /sysastuce globale pour obtenir une perspective beaucoup plus large sur les pilotes utilisés par quels périphériques (mais pas nécessairement ceux avec un fichier de périphérique):

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

Mise à jour

En regardant de plus près le résultat de udevadm, cela semble fonctionner en trouvant le /sysrépertoire canonique (comme si vous annuliez la référence aux répertoires majeur / mineur ci-dessus), puis en remontant dans l’arborescence de répertoires, en affichant toutes les informations qu’il trouve. De cette façon, vous obtenez des informations sur les périphériques parents et sur les pilotes qu’ils utilisent également.

Pour expérimenter cela, j'ai écrit le script ci-dessous pour parcourir l'arborescence de répertoires et afficher des informations à chaque niveau pertinent. udevsemble rechercher des fichiers lisibles à chaque niveau, avec leurs noms et contenus incorporés dans ATTRS. Au lieu de cela, j'affiche le contenu des ueventfichiers à chaque niveau (apparemment, sa présence définit un niveau distinct plutôt qu'un simple sous-répertoire). Je montre également le nom de base de tous les liens de sous-système que je trouve et cela montre comment le périphérique s'inscrit dans cette hiérarchie. udevadmn’affiche pas la même information, c’est donc un bel outil complémentaire. Les informations sur le périphérique parent (par exemple, les PCIinformations) sont également utiles si vous souhaitez faire correspondre la sortie d’autres outils, tels que lshwles périphériques de niveau supérieur.

#!/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
la source
Existe-t-il un moyen de déterminer tous les pilotes utilisés? Comme par exemple la udevadmréponse vous donnera sdet ahci. Y at-il un moyen de déterminer ahciest utilisé aussi?
Patrick
@ Patrick, oui, mis à jour.
Graeme
Super réponse, merci! Juste pour noter, dans mon cas, le lien était dedans device/device/, donc ma readlinkcommande ressemblait à readlink /sys/dev/char/XX\:Y/device/device/driver.
Harry Cutts
19

Vous pouvez utiliser l' udevadmoutil pour découvrir cela.
La commande serait udevadm info -a -n /dev/sda, puis regardez les DRIVER==paramètres.

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

Cela montre qu’il existe en réalité 2 pilotes impliqués dans la fourniture de ce périphérique, sdet ahci. Le premier sdest directement responsable du /dev/sdapériphérique, mais il utilise le ahcipilote sous-jacent.

 

La sortie de la udevadmcommande ressemble à ceci et inclut une description de son fonctionnement.

# 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
la source
1
@ECarterYoung Où voyez-vous qui udevadmest supprimé (ou même recommandé)? Je ne trouve rien qui donne un indice à cela.
Patrick
1
@ECarterYoung j'ai fait, je ne vois rien de la sorte.
Patrick
Je me suis trompé en ce qui concerne l'absence de UEVENT_HELPER dans le noyau. Sur les systèmes exécutant systemd, cette entrée est vide, mais le helpr est toujours présent sur le système.
eyoung100
4

Utilisez la commande hwinfo et le modèle et le pilote de sortie. S'il n'y a pas de pilote, il ne sera pas affiché. Par exemple pour les disques:

# hwinfo --block | grep -Ei "pilote \: | model \:"
  Modèle: "Disquette"
  Modèle: "FUJITSU MHZ2080B"
  Pilote: "ahci", "sd"
  Modèle: "Partition"
  Modèle: "Partition"
  Modèle: "Partition"
  Modèle: "Multi-Card générique"
  Pilote: "ums-realtek", "sd"
  Modèle: "Realtek USB2.0-CRW"
  Pilote: "ums-realtek"

Pour les cartes réseau:

# hwinfo --netcard | grep -Ei "pilote \: | model \:"
  Modèle: "Broadcom NetXtreme BCM5764M Ethernet PCIe Gigabit"
  Pilote: "tg3"
  Modèle: "Intel Wireless WiFi Link 5100"
  Pilote: "iwlwifi"

Pour les périphériques USB:

# hwinfo --usb | grep -Ei "pilote \: | model \:"
  Modèle: "Contrôleur d'hôte UHCI Linux 3.11.10-7-desktop-uhci_hcd"
  Pilote: "hub"
  Modèle: "Contrôleur d'hôte UHCI Linux 3.11.10-7-desktop-uhci_hcd"
  Pilote: "hub"
  Modèle: "IDEACOM IDC 6680"
  Pilote: "usbhid"
  [...]

Utilisez hwinfo --help pour déterminer quels autres types de périphériques vous pouvez interroger. hwinfo est installé par défaut, par exemple sur SUSE Linux.

Thorsten Staerk
la source
Pour associer cela à un fichier de périphérique particulier, une solution consiste à ajouter l' --onlyoption. Par exemple hwinfo --block --only /dev/sda | grep ....
Graeme
3

lshwest un outil génial pour lister le matériel trouvé sur votre machine. Vous devrez d'abord l'installer avant de l'exécuter.

$ yum install lshw
$ apt-get install lshw

Utilisez yumou apt-getselon le système que vous utilisez. Ensuite, pour lister spécifiquement le matériel de stockage:

# 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

Vous voudrez peut-être l'exécuter rootpour récupérer toutes les informations.

Sinon, lspcipeut également donner des informations sur votre matériel:

$ 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

Pour connaître le numéro majeur et mineur d'un périphérique, exécutez- lsle simplement .

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

Dans cette sortie, bin brw-rw----.signifie qu'il s'agit d'un périphérique en mode bloc. Les chiffres 8et 0sont respectivement les numéros majeur et mineur de l'appareil.

Spack
la source
1
Ma question concerne la recherche du lien entre un périphérique et son module / pilote. Où répondez-vous cela?
Totor
1
@Totor Dans les deux sorties de lshwet lspcivous pouvez voir le module utilisé par un périphérique: configuration: driver = ahci latence = 0 et pilote du noyau utilisé: ahci .
Spack