Jak znaleźć sterownik (moduł) powiązany z urządzeniem w systemie Linux?

50

W systemie Linux, biorąc pod uwagę:

  • urządzenie, na przykład /dev/sda,
  • i jej główne i poboczne numery, na przykład 8, 0,

skąd mam wiedzieć, który moduł / sterownik go „prowadzi”?

Czy mogę to zagłębić /syslub /procodkryć?

Totor
źródło
Niektóre połączenia lsmod, /proc/modulesi modinfo?
4
stackoverflow.com/questions/2911050 wygląda tak samo jak to pytanie.
Michael Tomkins
Totor, dodałem nagrodę, ponieważ inny użytkownik wysłał to samo pytanie, ponieważ uważał, że nie otrzymał on wystarczającej uwagi. Poprosiłem go o usunięcie jego pytania i zaoferowałem nagrodę za to, aby uzyskać więcej odpowiedzi. Pamiętaj, aby zaakceptować jedną z poniższych odpowiedzi, jeśli odpowiedzą na twoje pytanie.
terdon
@terdon dziękuję za nagrodę, to dało miłe odpowiedzi. Jeszcze nie wszystko dokładnie przetestowałem, ale tymczasem zaakceptuję odpowiedź Graeme .
Totor

Odpowiedzi:

58

Aby uzyskać te informacje z sysfspliku urządzenia, najpierw określ numer główny / pomocniczy, patrząc na wynik ls -lnp

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

8, 0Mówi nam, że liczba ta jest głównym 8i moll 0. Na bpoczątku listy znajduje się także informacja, że ​​jest to urządzenie blokowe. Inne urządzenia mogą mieć cna początku urządzenie postaci.

Jeśli spojrzysz poniżej /sys/dev, zobaczysz, że są dwa katalogi. Jeden dzwonił, blocka drugi dzwonił char. Nie trzeba tutaj myśleć, że są one odpowiednio dla urządzeń blokowych i postaci. To urządzenie jest następnie dostępne pod jego głównym / podrzędnym numerem w tym katalogu. Jeśli dla urządzenia dostępny jest sterownik, można go znaleźć, czytając cel driverłącza w tym lub devicepodkatalogu. Na przykład /dev/sdamogę po prostu zrobić:

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

To pokazuje, że sdsterownik jest używany dla urządzenia. Jeśli nie masz pewności, czy urządzenie jest urządzeniem blokowym lub znakowym, w powłoce możesz po prostu zastąpić tę część znakiem *. Działa to równie dobrze:

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

Dostęp do urządzeń blokowych można również uzyskać bezpośrednio poprzez ich nazwę za pomocą jednego /sys/blocklub dwóch /sys/class/block. Na przykład:

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

Zauważ, że istnienie różnych katalogów /sysmoże się zmieniać w zależności od konfiguracji jądra. Również nie wszystkie urządzenia mają devicepodfolder. Tak jest na przykład w przypadku plików urządzeń partycji, takich jak /dev/sda1. Tutaj musisz uzyskać dostęp do urządzenia dla całego dysku (niestety nie ma sysdo tego linków).

Ostatnią rzeczą, która może być przydatna, jest lista sterowników dla wszystkich urządzeń, dla których są one dostępne. W tym celu można użyć globs, aby wybrać wszystkie katalogi, w których znajdują się łącza sterowników. Na przykład:

$ 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

Na koniec, aby nieco odejść od pytania, dodam kolejną /sysglobalną sztuczkę, aby uzyskać znacznie szerszą perspektywę, które sterowniki są używane przez poszczególne urządzenia (choć niekoniecznie te z plikiem urządzenia):

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

Aktualizacja

Przyglądając się dokładniej wynikowi udevadm, wydaje się, że działa, znajdując /syskatalog kanoniczny (tak jak w przypadku wyrejestrowania głównych / mniejszych katalogów powyżej), a następnie przesuwając się w górę drzewa katalogów, wypisując wszelkie znalezione informacje. W ten sposób otrzymujesz informacje o urządzeniach nadrzędnych i wszelkich używanych przez nich sterownikach.

Aby eksperymentować z tym, napisałem poniższy skrypt, aby przejść do drzewa katalogów i wyświetlić informacje na każdym odpowiednim poziomie. udevwydaje się szukać plików na każdym poziomie z włączonymi ich nazwami i zawartością ATTRS. Zamiast tego wyświetlam zawartość ueventplików na każdym poziomie (pozornie obecność tego określa odrębny poziom, a nie tylko podkatalog). Pokazuję również basename wszystkich znalezionych linków podsystemów, a to pokazuje, jak urządzenie pasuje do tej hierarchii. udevadmnie wyświetla tych samych informacji, więc jest to miłe narzędzie uzupełniające. Informacje o urządzeniu nadrzędnym (np. PCIInformacje) są również przydatne, jeśli chcesz dopasować dane wyjściowe innych narzędzi, takich jak lshwurządzenia wyższego poziomu.

#!/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
źródło
Czy jest jakiś sposób na określenie wszystkich używanych sterowników? Na przykład udevadmodpowiedź da ci sdi ahci. Czy istnieje sposób, aby ustalić, ahciczy również jest używany?
Patrick,
@Patrick, tak, zaktualizowano.
Graeme,
Świetna odpowiedź, dzięki! Uwaga: w moim przypadku link był włączony device/device/, więc moje readlinkpolecenie wyglądało tak readlink /sys/dev/char/XX\:Y/device/device/driver.
Harry Cutts
19

Możesz użyć tego udevadmnarzędzia, aby to odkryć.
Polecenie to udevadm info -a -n /dev/sda, a następnie spójrz na DRIVER==parametry.

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

To pokazuje, że w rzeczywistości w zapewnienie tego urządzenia są zaangażowane 2 sterowniki, sdoraz ahci. Pierwszy sdjest bezpośrednio odpowiedzialny za /dev/sdaurządzenie, ale korzysta ze ahcisterownika pod spodem.

 

Dane wyjściowe udevadmpolecenia wyglądają tak i zawierają opis działania.

# 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
źródło
1
@ECarterYoung Gdzie widzisz, że udevadmzostał usunięty (a nawet zalecany)? Nie mogę znaleźć niczego, co dałoby na to podpowiedź.
Patrick,
1
@ECarterYoung Zrobiłem, nic takiego nie widzę.
Patrick,
Myliłem się co do braku UEVENT_HELPER w jądrze. W systemach z systemem systemd ten wpis jest pusty, ale helpr jest nadal obecny w systemie.
eyoung100
4

Użyj polecenia hwinfo oraz modelu wyjściowego i sterownika. Jeśli nie ma sterownika, nie zostanie wyświetlony. Na przykład dla dysków:

# hwinfo --block | grep -Ei "sterownik \: | model \:"
  Model: „dyskietka”
  Model: „FUJITSU MHZ2080B”
  Sterownik: „ahci”, „sd”
  Model: „partycja”
  Model: „partycja”
  Model: „partycja”
  Model: „Generic Multi-Card”
  Sterownik: „ums-realtek”, „sd”
  Model: „Realtek USB2.0-CRW”
  Sterownik: „ums-realtek”

W przypadku kart sieciowych:

# hwinfo --netcard | grep -Ei "sterownik \: | model \:"
  Model: „Broadcom NetXtreme BCM5764M Gigabit Ethernet PCIe”
  Sterownik: „tg3”
  Model: „Intel Wireless WiFi Link 5100”
  Sterownik: „iwlwifi”

W przypadku urządzeń USB:

# hwinfo --usb | grep -Ei "sterownik \: | model \:"
  Model: „Linux 3.11.10-7-desktop uhci_hcd Kontroler hosta UHCI”
  Sterownik: „hub”
  Model: „Linux 3.11.10-7-desktop uhci_hcd Kontroler hosta UHCI”
  Sterownik: „hub”
  Model: „IDEACOM IDC 6680”
  Sterownik: „usbhid”
  [...]

Użyj hwinfo --help, aby dowiedzieć się, jakie inne typy urządzeń możesz zapytać. hwinfo jest instalowane domyślnie np. w SUSE Linux.

Thorsten Staerk
źródło
Aby powiązać to z konkretnym plikiem urządzenia, jednym ze sposobów jest dodanie --onlyopcji. Np hwinfo --block --only /dev/sda | grep ....
Graeme,
3

lshwto niesamowite narzędzie do wyświetlania listy sprzętu znalezionego w twoim komputerze. Przed uruchomieniem musisz go najpierw zainstalować.

$ yum install lshw
$ apt-get install lshw

Użyj yumlub w apt-getzależności od używanego systemu. Następnie, aby szczegółowo wymienić sprzęt pamięci masowej:

# 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

Możesz go uruchomić, rootaby odzyskać wszystkie informacje.

W przeciwnym razie lspcimoże również podać informacje o twoim sprzęcie:

$ 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

Aby dowiedzieć się o głównej i mniejszej liczbie urządzeń, po prostu lsna nim uruchom .

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

W tym wyjściu bin brw-rw----.oznacza, że ​​jest to urządzenie blokowe. Cyfry 8i 0są odpowiednio główną i podrzędną liczbą urządzenia.

Spack
źródło
1
Moje pytanie dotyczy znalezienia połączenia między jednym urządzeniem a jego modułem / sterownikiem. Gdzie na to odpowiadasz?
Totor
1
@Totor Zarówno wyjście lshwi lspcimożna zobaczyć moduł używany przez urządzenie: konfiguracja: driver = AHCI latency = 0 i sterownik jądra w użyciu: AHCI .
Spack