Как найти драйвер (модуль), связанный с устройством в Linux?


50

На Linux дано:

  • устройство, например /dev/sda,
  • и его старшие и младшие номера, например 8, 0,

как я могу узнать, какой модуль / драйвер его "ведет"?

Могу ли я покопаться /sysили /procоткрыть это?


Какая-то комбинация lsmod, /proc/modulesа modinfo?

4
stackoverflow.com/questions/2911050 выглядит так же, как этот вопрос.
Майкл Томкинс


Тотор, я добавил награду, потому что другой пользователь отправил тот же вопрос, потому что он чувствовал, что этому вопросу не уделялось достаточно внимания. Я попросил его удалить свой вопрос и предложил вознаграждение за этот вопрос, чтобы получить больше ответов. Пожалуйста, не забудьте принять один из ответов ниже, если они ответят на ваш вопрос.
Terdon

@terdon спасибо за награду, она дала хорошие ответы. Я еще не все тщательно проверил, но тем временем приму ответ Грэма .
Тотор

Ответы:


58

Чтобы получить эту информацию sysfsдля файла устройства, сначала определите старший / младший номер, посмотрев на вывод ls -l, например,

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

Это 8, 0говорит нам, что старшее число есть, 8а младшее есть 0. В bначале списка также говорится, что это блочное устройство. Другие устройства могут иметь cсимвольное устройство в начале.

Если вы посмотрите вниз /sys/dev, вы увидите, что есть две директории. Один звонил, blockа другой звонил char. Понятно, что они предназначены для блочных и символьных устройств соответственно. Каждое устройство затем доступно по его старшему / младшему номеру в этом каталоге. Если для устройства доступен драйвер, его можно найти, прочитав цель driverссылки в этом или deviceподкаталоге. Например, для моего /dev/sdaя могу просто сделать:

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

Это показывает, что sdдрайвер используется для устройства. Если вы не уверены, является ли устройство блочным или символьным устройством, в оболочке вы можете просто заменить эту часть на *. Это работает так же хорошо:

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

Доступ к блочным устройствам также можно получить напрямую через их имя через /sys/blockили /sys/class/block. Например:

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

Обратите внимание, что наличие различных каталогов /sysможет меняться в зависимости от конфигурации ядра. Также не все устройства имеют deviceподпапку. Например, это относится к файлам устройств разделов, таким как /dev/sda1. Здесь вы должны получить доступ к устройству для всего диска (к сожалению, sysдля этого нет ссылок).

Последнее, что может быть полезно сделать, - перечислить драйверы для всех устройств, для которых они доступны. Для этого вы можете использовать globs для выбора всех каталогов, в которых есть ссылки на драйверы. Например:

$ 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

Наконец, чтобы немного отклониться от вопроса, я добавлю еще один /sysхитрый трюк, чтобы получить более широкое представление о том, какие драйверы используются какими устройствами (хотя и не обязательно теми, которые имеют файл устройства):

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

Обновить

При более внимательном рассмотрении выходных данных udevadmон, похоже, работает, находя канонический /sysкаталог (как вы могли бы получить, если вы разыменовали основные / второстепенные каталоги выше), а затем прокладывал путь вверх по дереву каталогов, распечатывая любую найденную информацию. Таким образом, вы получаете информацию о родительских устройствах и любых драйверах, которые они используют.

Чтобы поэкспериментировать с этим, я написал скрипт ниже, чтобы пройтись по дереву каталогов и отобразить информацию на каждом соответствующем уровне. udevПохоже, что на каждом уровне ищут читаемые файлы с их именами и содержимым ATTRS. Вместо этого я отображаю содержимое ueventфайлов на каждом уровне (по-видимому, наличие этого определяет отдельный уровень, а не просто подкаталог). Я также показываю базовое имя любых ссылок на подсистемы, которые я нахожу, и это показывает, как устройство вписывается в эту иерархию. udevadmне отображает ту же информацию, так что это хороший дополнительный инструмент. Информация о родительском устройстве (например, PCIинформация) также полезна, если вы хотите сопоставить выходные данные других инструментов, таких как lshwустройства более высокого уровня.

#!/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

Есть ли способ определить все используемые драйверы? Как например udevadmответ даст вам sdи ahci. Есть ли способ определить ahci, используется ли также?
Патрик

@ Патрик, да, обновлено.
Грэм

Отличный ответ, спасибо! Просто чтобы заметить, в моем случае ссылка была device/device/, поэтому моя readlinkкоманда выглядела так readlink /sys/dev/char/XX\:Y/device/device/driver.
Гарри Каттс

19

Вы можете использовать udevadmинструмент, чтобы обнаружить это.
Команда будет udevadm info -a -n /dev/sda, а затем посмотрите на DRIVER==параметры.

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

Это показывает, что на самом деле в обеспечении этого устройства участвуют 2 драйвера, sdи ahci. Первый, sdнепосредственно отвечает за /dev/sdaустройство, но использует ahciдрайвер под ним.

 

Вывод udevadmкоманды выглядит следующим образом и включает описание того, как она работает.

# 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 Где вы видите, что udevadmудалено (или даже рекомендуется)? Я не могу найти ничего, даже намекая на это.
Патрик

1
@ECarterYoung Я сделал, я не вижу ничего подобного.
Патрик

Я ошибся в связи с отсутствием UEVENT_HELPER в ядре. В системах, работающих под управлением systemd, эта запись пуста, но в системе все еще присутствует helpr.
eyoung100

4

Используйте команду hwinfo и выведите модель и драйвер. Если нет драйвера, он не будет показан. Например для дисков:

# hwinfo --block | grep -Ei "водитель \: | модель \:"
  Модель: "Флоппи-диск"
  Модель: "FUJITSU MHZ2080B"
  Водитель: "Ahci", "SD"
  Модель: "Перегородка"
  Модель: "Перегородка"
  Модель: "Перегородка"
  Модель: "Универсальная мультикарта"
  Водитель: "умс-реалтек", "сд"
  Модель: "Realtek USB2.0-CRW"
  Водитель: "Ум-Реалтек"

Для сетевых карт:

# hwinfo --netcard | grep -Ei "водитель \: | модель \:"
  Модель: "Broadcom NetXtreme BCM5764M Гигабитный Ethernet PCIe"
  Водитель: "tg3"
  Модель: "Intel Wireless WiFi Link 5100"
  Водитель: "iwlwifi"

Для USB-устройств:

# hwinfo --usb | grep -Ei "водитель \: | модель \:"
  Модель: «Linux 3.11.10-7-desktop uhci_hcd UHCI Host Controller»
  Водитель: "хаб"
  Модель: «Linux 3.11.10-7-desktop uhci_hcd UHCI Host Controller»
  Водитель: "хаб"
  Модель: "IDEACOM IDC 6680"
  Водитель: "usbhid"
  [...]

Используйте hwinfo --help, чтобы узнать, какие другие типы устройств вы можете запросить. hwinfo устанавливается по умолчанию, например, в SUSE Linux.


Чтобы связать это с конкретным файлом устройства, одним из способов является добавление --onlyопции. Например hwinfo --block --only /dev/sda | grep ....
Грэм

3

lshwэто удивительный инструмент для перечисления оборудования, найденного на вашем компьютере. Вы должны будете установить его перед запуском.

$ yum install lshw
$ apt-get install lshw

Используйте yumили в apt-getзависимости от системы, которую вы используете. Затем, чтобы конкретно перечислить оборудование для хранения:

# 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

Вы можете запустить его, rootчтобы получить всю информацию обратно.

В противном случае lspciтакже можете предоставить информацию о вашем оборудовании:

$ 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

Чтобы узнать старший и младший номер устройства, просто запустите lsна нем.

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

В этом выводе bin brw-rw----.означает, что это блочное устройство. Цифры 8и 0являются соответственно старшим и младшим номером устройства.


1
Мой вопрос касается нахождения связи между одним устройством и его модулем / драйвером. Где ты на это отвечаешь?
Тотор

1
@Totor В обоих выходных данных lshwи lspciвы можете увидеть модуль, используемый устройством: configuration: driver = ahci latency = 0 и используемый драйвер ядра: ahci .
Спак
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.