如何在 Linux 上找到与设备关联的驱动程序(模块)?

Tot*_*tor 68 linux drivers kernel-modules

在 Linux 上,给出:

  • 一个设备,例如/dev/sda
  • 以及它的主要和次要号码,例如8, 0

我怎么知道哪个模块/驱动程序在“驱动”它?

我可以深入研究/sys/proc发现吗?

Gra*_*eme 79

要从sysfs设备文件中获取此信息,首先通过查看 的输出来确定主要/次要编号ls -l,例如

 $ ls -l /dev/sda
 brw-rw---- 1 root disk 8, 0 Apr 17 12:26 /dev/sda
Run Code Online (Sandbox Code Playgroud)

8, 0告诉我们,主号码8和未成年人0。将b在该列表的开始也告诉我们,这是一个块设备。其他设备可能c在开始时有一个for 字符设备。

如果你再往下看/sys/dev,你会看到有两个目录。一个叫block一个叫char。这里显而易见的是,它们分别用于块设备和字符设备。然后每个设备都可以通过其主要/次要编号访问此目录。如果设备有可用的驱动程序,则可以通过读取driverdevice目录或子目录中的链接目标来找到它。例如,对于我来说,/dev/sda我可以简单地做:

$ readlink /sys/dev/block/8\:0/device/driver
../../../../../../../bus/scsi/drivers/sd
Run Code Online (Sandbox Code Playgroud)

这表明sd驱动程序用于设备。如果您不确定设备是块设备还是字符设备,在 shell 中,您可以简单地将此部分替换为*. 这也同样有效:

$ readlink /sys/dev/*/8\:0/device/driver
../../../../../../../bus/scsi/drivers/sd
Run Code Online (Sandbox Code Playgroud)

块设备也可以通过它们的名称通过/sys/block或直接访问/sys/class/block。例如:

$ readlink /sys/block/sda/device/driver
../../../../../../../bus/scsi/drivers/sd
Run Code Online (Sandbox Code Playgroud)

请注意,in 中各种目录的存在/sys可能会因内核配置而异。也并非所有设备都有device子文件夹。例如,分区设备文件(如/dev/sda1. 在这里,您必须访问整个磁盘的设备(不幸的是,没有相关sys链接)。

最后一件有用的事情是列出所有可用设备的驱动程序。为此,您可以使用 globs 选择存在驱动程序链接的所有目录。例如:

$ ls -l /sys/dev/*/*/device/driver && ls -l /sys/dev/*/*/driver 
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
Run Code Online (Sandbox Code Playgroud)

最后,为了稍微偏离这个问题,我将添加另一个/sys全局技巧,以更广泛地了解哪些设备正在使用哪些驱动程序(尽管不一定是那些带有设备文件的驱动程序):

find /sys/bus/*/drivers/* -maxdepth 1 -lname '*devices*' -ls
Run Code Online (Sandbox Code Playgroud)

更新

更仔细地查看 的输出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
Run Code Online (Sandbox Code Playgroud)


phe*_*mer 25

您可以使用该udevadm工具来发现这一点。
命令将是udevadm info -a -n /dev/sda,然后查看DRIVER==参数。

# udevadm info -a -n /dev/sda | grep -oP 'DRIVERS?=="\K[^"]+'  
sd
ahci
Run Code Online (Sandbox Code Playgroud)

这表明提供此设备实际上涉及 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==""
Run Code Online (Sandbox Code Playgroud)


Tho*_*erk 8

使用命令 hwinfo并输出模型和驱动程序。如果没有驱动程序,则不会显示。例如对于磁盘:

# hwinfo --block | grep -Ei "driver\:|model\:"
  型号:“软盘”
  型号:“富士通MHZ2080B”
  驱动程序:“ahci”,“sd”
  型号:“分区”
  型号:“分区”
  型号:“分区”
  型号:“通用多卡”
  驱动程序:“ums-realtek”、“sd”
  型号:“Realtek USB2.0-CRW”
  驱动程序:“ums-realtek”

对于网卡:

# hwinfo --netcard | grep -Ei "driver\:|model\:"
  型号:“Broadcom NetXtreme BCM5764M 千兆以太网 PCIe”
  驱动程序:“tg3”
  型号:“英特尔无线 WiFi Link 5100”
  驱动程序:“iwlwifi”

对于 USB 设备:

# hwinfo --usb | grep -Ei "driver\:|model\:"
  型号:“Linux 3.11.10-7-desktop uhci_hcd UHCI 主机控制器”
  司机:“枢纽”
  型号:“Linux 3.11.10-7-desktop uhci_hcd UHCI 主机控制器”
  司机:“枢纽”
  型号:“IDEACOM IDC 6680”
  司机:“usbhid”
  [...]

使用 hwinfo --help 找出您可以查询的其他设备类型。hwinfo 是默认安装的,例如在 SUSE Linux 上。


Spa*_*ack 5

lshw是一个很棒的工具,可以列出您机器中找到的硬件。在运行之前您必须先安装它。

$ yum install lshw
$ apt-get install lshw
Run Code Online (Sandbox Code Playgroud)

使用yumapt-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
Run Code Online (Sandbox Code Playgroud)

您可能想要运行它以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
Run Code Online (Sandbox Code Playgroud)

要找出设备的主设备号和次设备号,只需ls在设备上运行即可。

$ ls -l /dev/sda
brw-rw----. 1 root disk 8, 0 13 avril 10:54 /dev/sda
Run Code Online (Sandbox Code Playgroud)

在此输出中,inb表示brw-rw----.这是一个块设备。数字80分别是设备的主编号和次编号。