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


48

在Linux上,给出:

  • 设备,例如/dev/sda
  • 及其主要和次要数字,例如8, 0

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

我可以深入研究/sys还是/proc发现它?


的某种组合lsmod/proc/modulesmodinfo



Totor,我添加了赏金,因为另一个用户发布了相同的问题,因为他觉得这个问题没有得到足够的重视。我要求他删除他的问题,并为此悬赏以获取更多答案。如果他们回答了您的问题,请记住接受以下答案之一。
terdon

@terdon感谢您的赏金,它产生了不错的答案。我尚未仔细测试所有内容,但同时将接受Graeme的回答。
Totor

Answers:


56

要从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开始就带有for字符设备。

如果您随后查看/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目录来工作(如取消引用上面的main / minor目录时所得到的),然后沿目录树向上移动,打印出找到的所有信息。这样,您可以获得有关父设备及其使用的任何驱动程序的信息。

为了对此进行试验,我在下面编写了脚本以遍历目录树并在每个相关级别显示信息。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答案将给您sdahci。有没有办法确定ahci是否正在使用?
Patrick

@Patrick,是的,已更新。
Graeme 2014年

好答案,谢谢!请注意,在我的情况下,链接已插入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被删除(甚至推荐)?我什至找不到任何提示。
Patrick

1
@ECarterYoung我做到了,我什么也没看到。
Patrick

我误认为内核中没有UEVENT_HELPER。在运行systemd的系统上,该条目为空白,但系统上仍然存在帮助程序。
eyoung100

4

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

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

对于网卡:

#hwinfo --netcard | grep -Ei“ driver \:| model \:”
  型号:“ Broadcom NetXtreme BCM5764M千兆以太网PCIe”
  驱动程序:“ tg3”
  型号:“ Intel Wireless WiFi Link 5100”
  司机:“ iwlwifi”

对于USB设备:

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

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


要将其与特定的设备文件相关联,一种方法是添加--only选项。例如hwinfo --block --only /dev/sda | grep ...
Graeme 2014年

3

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

$ yum install lshw
$ apt-get install lshw

使用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

您可能需要运行它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----.表示这是一个块设备。数字80是设备的主要和次要数字。


1
我的问题是关于找到一台设备与其模块/驱动程序之间的链接。你在哪里回答?
Totor

1
@Totor在的两个输出中lshwlspci您可以看到设备使用的模块:配置:driver = ahci等待时间= 0正在使用的内核驱动程序:ahci
Spack
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.