我知道OP已经得到了关于狭窄问题的正确答案,但是我认为更符合SO精神的是将答案概括,因此我发帖希望它对回答概括性问题有所帮助:如何查找/dev/xyz使用的驱动程序?
选项1:浏览/sys文件系统
假设您已经挂载了sysfs
(通常在/sys
上;但我还没有找到一个不这样做的发行版),为什么不问内核呢?
1. 找出设备类型(字符/块)和节点号:
$ ls -l /dev/rtc0
crw------- 1 root root 249, 0 2019-04-01 15:22:29 /dev/rtc0
^ ^ ^
+-> character device +---+-> Major and minor node numbers.
第二步,将数字替换到/sys/dev路径中,如下所示(char
表示字符设备,block
表示块设备)。
$ cat /sys/dev/char/249:0/name
rtc_cmos 00:00
这是连接到节点的内核模块的名称。无论模块是链接到内核还是通过modprobe加载,它都起同样的作用。(而
00:00
不是RTC时钟中的时间。据我所知,它是父驱动程序或总线上其“功能”的设备地址;但请不要相信我,我只是隐约记得)。
附带说明,请放心探索此文件系统。它可被非root用户读取(除了安全敏感的部分,大多数可用root读取),完全可安全阅读,并且您可以在其中找到许多硬件和低级软件配置信息。与
/proc
的大部分内容不同,
/sys
的大部分内容是可写的,并且由程序用于更改运行中的内核和设备参数。例如,sysctl完全通过这个目录实现。但我跑题了。
选项2:使用udevadm
查找/sys
如果您有可用的udevadm,请向它询问关于设备的所有已知信息(该程序接受设备的/dev
和/sys
路径):
$ udevadm info -a /dev/rtc0
[...snip intro text...]
looking at device '/devices/pnp0/00:00/rtc/rtc0':
KERNEL=="rtc0"
SUBSYSTEM=="rtc"
DRIVER==""
ATTR{date}=="2019-06-27"
ATTR{hctosys}=="1"
ATTR{max_user_freq}=="64"
ATTR{name}=="rtc_cmos 00:00"
ATTR{since_epoch}=="1561605536"
ATTR{time}=="03:18:56"
ATTR{wakealarm}==""
looking at parent device '/devices/pnp0/00:00':
KERNELS=="00:00"
SUBSYSTEMS=="pnp"
DRIVERS=="rtc_cmos" <== THIS
ATTRS{id}=="PNP0b00"
ATTRS{nvram}==""
ATTRS{options}==""
looking at parent device '/devices/pnp0':
KERNELS=="pnp0"
SUBSYSTEMS==""
DRIVERS==""
info
命令告诉 udevadm 输出设备的全部信息,
-a
选项则用于沿着父级驱动程序/总线链向上获取信息。下面可以看到父设备
/devices/pnp0/00:00
使用了驱动程序
rtc_cmos
,并在由另一个设备
pnp0
创建的总线上被发现/激活,该设备是即插即用总线枚举器。
顺便提一下,udevadm 打印的名称也是 sysfs 中的路径,即您可以通过在 sysfs 挂载点
/sys
前缀来在普通文件空间中查看它们。
$ ls -l /sys/devices/pnp0/00:00/rtc/rtc0
$ ls -l /sys/dev/char/249:0/
这两个命令将生成相同的输出。
有一个注意点,与“普通”文件系统不同,sysfs硬链接目录,因此不要尝试在其中进行任何递归搜索(例如“find . /sys”或“ls -R /sys”)--这些程序将在文件系统上无限循环后崩溃。
那么,/sys/class/rtc/rtc0/device/rtc/rtc0
怎么样?
正如您所注意到的,从sysfs根目录到设备参数节点有多个路径。哪一个才是真正的诺依曼机器?
并非每个设备都通过/dev
文件系统(或任何其他文件系统)具有接口(与/dev
没有任何特殊之处--它只是一个tempfs;/dev/rtc0
是特殊的文件)。您无法通过路径/sys/dev/*
找到这些设备。
并非每个设备都是子系统的一部分,这也是可选的。您无法通过/sys/class*
发现这些设备。因此,这也是一个有用但可选的链接。请注意,此节点不同:它必须公开特定于子系统的参数。在我们的情况下,所有RTC时钟都公开了一组与rtc
subsystem通用的已知设置。
现在,/sys/devices/pnp0/00:00/rtc/rtc0
是到设备sysfs节点的主要、规范路径。它始终对应于其在系统总线和驱动程序层次结构中的拓扑位置:这是设备rtc
的实例rtc0
,在总线pnp0
上的地址为00:00
。它并不总是对应于其物理连接;在我们的情况下,pnp0
是一个虚拟总线,它不连接设备到物理总线和桥接器,只发现和枚举它们。这是udev用来唯一标识设备的规范名称(当然,去掉/sys
前缀--它只是一个挂载点)。
最后,内核模块不必在sysfs中公开任何内容。仅需从用户空间发现内核模块即可。但如果它确实这样做了,那么该模块将决定公开什么,而它的父级和祖先将决定它在devices
根下的sysfs中的位置。
$ grep CMOS /usr/src/linux/.config CONFIG_GENERIC_CMOS_UPDATE=y CONFIG_RTC_DRV_CMOS=y
- oz123CONFIG_EFI=y
,但是在grep CONFIG_RTC /usr/src/linux/.config | grep -i EFI
中没有找到任何相关内容。 - oz123