Làm cách nào để tìm trình điều khiển (mô-đun) được liên kết với thiết bị trên Linux?


48

Trên Linux, được đưa ra:

  • một thiết bị, ví dụ /dev/sda,
  • và số chính và số phụ của nó, ví dụ 8, 0,

Làm thế nào tôi có thể biết mô-đun / trình điều khiển nào đang "lái" nó?

Tôi có thể đào sâu /syshoặc /prockhám phá điều đó không?


Một số kết hợp lsmod, /proc/modulesmodinfo?

4
stackoverflow.com/questions/2911050 trông giống như câu hỏi này.
Michael Tomkins


Totor, tôi đã thêm tiền thưởng vì một người dùng khác đã đăng câu hỏi tương tự vì anh ta cảm thấy rằng người này đã không nhận được đủ sự chú ý. Tôi yêu cầu anh ta xóa câu hỏi của anh ta và đưa ra một tiền thưởng cho câu hỏi này để có thêm câu trả lời. Hãy nhớ chấp nhận một trong những câu trả lời dưới đây nếu họ trả lời câu hỏi của bạn.
terdon

@terdon cảm ơn vì tiền thưởng, nó đã tạo ra những câu trả lời hay. Tôi chưa cẩn thận kiểm tra mọi thứ, nhưng sẽ chấp nhận câu trả lời của Graeme trong khi đó.
Totor

Câu trả lời:


56

Để lấy thông tin này từ sysfsmột tệp thiết bị, trước tiên hãy xác định số chính / phụ bằng cách xem đầu ra của ls -l, vd

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

Điều này 8, 0cho chúng ta biết rằng số chính là 8và số phụ là 0. Khi bbắt đầu danh sách cũng cho chúng ta biết rằng đó là một thiết bị khối. Các thiết bị khác có thể có một cthiết bị cho nhân vật khi bắt đầu.

Nếu bạn nhìn vào bên dưới /sys/dev, bạn sẽ thấy có hai thư mục. Một người gọi blockvà một người gọi char. Không có trí tuệ ở đây là những thứ này dành cho các thiết bị khối và nhân vật tương ứng. Mỗi thiết bị sau đó có thể truy cập bằng số chính / phụ là thư mục này. Nếu có một trình điều khiển có sẵn cho thiết bị, nó có thể được tìm thấy bằng cách đọc mục tiêu của driverliên kết trong thư mục này hoặc devicethư mục con. Ví dụ, đối với tôi, /dev/sdatôi chỉ có thể làm:

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

Điều này cho thấy sdtrình điều khiển được sử dụng cho thiết bị. Nếu bạn không chắc thiết bị là thiết bị khối hay ký tự, trong vỏ bạn có thể chỉ cần thay thế phần này bằng a *. Điều này cũng hoạt động tốt:

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

Thiết bị chặn cũng có thể được truy cập trực tiếp thông qua tên của chúng thông qua /sys/blockhoặc /sys/class/block. Ví dụ:

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

Lưu ý rằng sự tồn tại của các thư mục khác nhau /syscó thể thay đổi tùy thuộc vào cấu hình kernel. Ngoài ra không phải tất cả các thiết bị đều có devicethư mục con. Ví dụ, đây là trường hợp cho các tập tin thiết bị phân vùng như /dev/sda1. Tại đây bạn phải truy cập thiết bị cho toàn bộ đĩa (tiếc là không có sysliên kết nào cho việc này).

Điều cuối cùng có thể hữu ích là liệt kê các trình điều khiển cho tất cả các thiết bị có sẵn. Đối với điều này, bạn có thể sử dụng các khối để chọn tất cả các thư mục chứa các liên kết trình điều khiển. Ví dụ:

$ 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

Cuối cùng, để chuyển hướng khỏi câu hỏi một chút, tôi sẽ thêm một /systhủ thuật toàn cầu khác để có góc nhìn rộng hơn nhiều về trình điều khiển nào đang được sử dụng bởi thiết bị nào (mặc dù không nhất thiết là những người có tệp thiết bị):

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

Cập nhật

Nhìn kỹ hơn vào đầu ra của udevadmnó, nó dường như hoạt động bằng cách tìm /systhư mục chính tắc (như bạn sẽ nhận được nếu bạn hủy đăng ký các thư mục chính / phụ ở trên), sau đó tìm đường lên cây thư mục, in ra bất kỳ thông tin nào nó tìm thấy. Bằng cách này, bạn sẽ có được thông tin về các thiết bị mẹ và bất kỳ trình điều khiển nào họ sử dụng.

Để thử nghiệm điều này, tôi đã viết kịch bản bên dưới để đi lên cây thư mục và hiển thị thông tin ở mỗi cấp độ có liên quan. udevdường như tìm kiếm các tập tin có thể đọc được ở mỗi cấp độ, với tên và nội dung của chúng được kết hợp vào ATTRS. Thay vì làm điều này, tôi hiển thị nội dung của các ueventtệp ở mỗi cấp độ (dường như sự hiện diện của điều này xác định một cấp độ khác biệt chứ không chỉ là một thư mục con). Tôi cũng hiển thị tên cơ sở của bất kỳ liên kết hệ thống con nào tôi tìm thấy và điều này cho thấy cách thiết bị phù hợp với hệ thống phân cấp này. udevadmkhông hiển thị cùng thông tin, vì vậy đây là một công cụ bổ trợ tốt. Thông tin thiết bị mẹ (ví dụ PCIthông tin) cũng hữu ích nếu bạn muốn khớp đầu ra của các công cụ khác như lshwvới các thiết bị cấp cao hơn.

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

Có cách nào để xác định tất cả các trình điều khiển đang được sử dụng? Ví dụ như udevadmcâu trả lời sẽ cho bạn sdahci. Có cách nào để xác định ahciđang được sử dụng không?
Patrick

@Patrick, vâng, cập nhật.
Graeme

Câu trả lời tuyệt vời, cảm ơn! Chỉ cần lưu ý, trong trường hợp của tôi là liên kết device/device/, vì vậy readlinklệnh của tôi trông như thế readlink /sys/dev/char/XX\:Y/device/device/driver.
Harry Cutts

19

Bạn có thể sử dụng udevadmcông cụ để khám phá điều này.
Lệnh sẽ là udevadm info -a -n /dev/sda, và sau đó nhìn vào các DRIVER==tham số.

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

Điều này cho thấy thực sự có 2 trình điều khiển liên quan đến việc cung cấp thiết bị này sdahci. Người đầu tiên, sdchịu trách nhiệm trực tiếp cho /dev/sdathiết bị, nhưng nó sử dụng ahcitrình điều khiển underneith.

 

Đầu ra của udevadmlệnh trông như thế này và bao gồm một mô tả về cách thức hoạt động của nó.

# 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 Bạn thấy nơi nào udevadmbị xóa (hoặc thậm chí được đề xuất)? Tôi không thể tìm thấy bất cứ điều gì thậm chí đưa ra một gợi ý về điều đó.
Patrick

1
@ECarterYoung Tôi đã làm, tôi không thấy gì cả.
Patrick

Tôi đã nhầm lẫn về sự vắng mặt của UEVENT_HELPER trong kernel. Trên các hệ thống đang chạy systemd, mục này trống, nhưng phần trợ giúp vẫn hiện diện trên hệ thống.
Eyoung100

4

Sử dụng lệnh hwinfo và mô hình đầu ra và trình điều khiển. Nếu không có trình điều khiển, nó sẽ không được hiển thị. Ví dụ cho các đĩa:

# hwinfo - chặn | grep -Ei "trình điều khiển \: | model \:"
  Model: "Đĩa mềm"
  Model: "FUJITSU MHZ2080B"
  Trình điều khiển: "ahci", "sd"
  Mô hình: "Phân vùng"
  Mô hình: "Phân vùng"
  Mô hình: "Phân vùng"
  Model: "Thẻ đa năng chung"
  Trình điều khiển: "ums-realtek", "sd"
  Model: "Realtek USB2.0-CRW"
  Tài xế: "ums-realtek"

Đối với thẻ mạng:

# hwinfo - thẻ từ | grep -Ei "trình điều khiển \: | model \:"
  Model: "Broadcom NetXtreme BCM5764M Gigabit Ethernet PCIe"
  Tài xế: "tg3"
  Model: "Liên kết WiFi không dây Intel 5100"
  Tài xế: "iwlwifi"

Đối với thiết bị USB:

# hwinfo --usb | grep -Ei "trình điều khiển \: | model \:"
  Model: "Bộ điều khiển máy chủ uhci_hcd UHCI trên máy tính để bàn"
  Tài xế: "trung tâm"
  Model: "Bộ điều khiển máy chủ uhci_hcd UHCI trên máy tính để bàn"
  Tài xế: "trung tâm"
  Mô hình: "IDEACOM IDC 6680"
  Trình điều khiển: "usbhid"
  [...]

Sử dụng hwinfo - trợ giúp để tìm hiểu những loại thiết bị khác mà bạn có thể truy vấn. hwinfo được cài đặt theo mặc định, ví dụ như trên SUSE Linux.


Để liên kết điều này với một tập tin thiết bị cụ thể, một cách là thêm --onlytùy chọn. Ví dụ hwinfo --block --only /dev/sda | grep ....
Graeme

3

lshwlà một công cụ tuyệt vời để liệt kê phần cứng được tìm thấy trong máy của bạn. Bạn sẽ phải cài đặt nó trước khi chạy.

$ yum install lshw
$ apt-get install lshw

Sử dụng yumhoặc apt-gettùy thuộc vào hệ thống bạn đang sử dụng. Sau đó, để liệt kê cụ thể phần cứng lưu trữ:

# 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

Bạn có thể muốn chạy nó rootđể lấy lại tất cả thông tin.

Nếu không, lspcicũng có thể cung cấp thông tin về phần cứng của bạn:

$ 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

Để tìm ra số lượng lớn và nhỏ của một thiết bị, chỉ cần chạy lstrên nó.

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

Sản lượng này, btrong brw-rw----.phương tiện rằng đây là một thiết bị khối. Các chữ số 80tương ứng là số chính và số phụ của thiết bị.


1
Câu hỏi của tôi là về việc tìm kiếm liên kết giữa một thiết bị và mô-đun / trình điều khiển của nó. Bạn trả lời ở đâu?
Totor

1
@Totor Trong cả hai đầu ra lshwlspcibạn có thể thấy mô-đun được sử dụng bởi một thiết bị: configure: driver = ahci latency = 0trình điều khiển Kernel đang sử dụng: ahci .
Spack
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.