如何找到内核加载的RTC模块?

时间:2017-12-22 11:28:35

标签: linux linux-kernel linux-device-driver

在使用从Ubuntu OS 16.04获得的配置文件编译我的内核期间,我注意到我正在编译许多RTC驱动程序,基本上每个可能的驱动程序:

... snip ...
CC [M]  drivers/rtc/rtc-bq4802.o
CC [M]  drivers/rtc/rtc-da9052.o 
CC [M]  drivers/rtc/rtc-da9055.o
... more of those ...
...

我想知道是否可以摆脱那么多司机,所以我开始四处寻找:

  1. 查看lsmod我看不到RTC驱动程序
  2. lshw也无济于事
  3. lspci -v也没有产生太多信息。
  4. 较低级别检查,显示设备存在:

    $ ls -l /dev/rtc
    lrwxrwxrwx 1 root root 4 Dec 18 09:54 /dev/rtc -> rtc0
    

    我得到更多信息的最近信息是/sys/class/rtc/

    $ sudo cat /sys/class/rtc/rtc0/device/rtc/rtc0/name 
    rtc_cmos
    

    Doe意味着我的内核使用的唯一驱动程序是rtc_cmos

    • 这是否意味着我不需要所有其他驱动程序?
    • 这是否意味着我的笔记本电脑使用CMOS兼容硬件?
    • 另外,modinfo rtc_cmos为什么不返回任何内容?

2 个答案:

答案 0 :(得分:3)

  

这是否意味着我不需要所有其他驱动程序?   这是否意味着我的笔记本电脑使用CMOS兼容硬件?

确切地说,如果你只关心那个RTC,那么rtc_cmos就是你所需要的。 如果你的电脑足够新,rtc-efi可能是一个有效的选择。

  

另外,为什么modinfo rtc_cmos什么都不返回?

因为驱动程序可能是在内核中静态编译而不是作为模块编译的。检查配置中的CONFIG_RTC_DRV_CMOS = y。

答案 1 :(得分:1)

我了解OP对狭窄问题的正确答案,但我觉得将答案归纳起来更符合SO精神,因此我将其发布,希望对回答广义问题会有所帮助:如何找到/dev/xyz使用的驱动程序?

选项1:拨入/ sys文件系统

假设您已安装sysfs(通常安装在/sys上;但是我还没有找到一个不需要的发行版),为什么不问内核本身呢?

1。找出device type (char/block) and the node number

$ 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.

2。将数字代入/ sys / dev路径,如下所示({char用于char设备,block是用于块设备)。

$ cat /sys/dev/char/249:0/name
rtc_cmos 00:00

这是连接到节点的内核模块的名称。无论模块是链接到内核还是通过modprobe加载,其工作方式都是相同的。 (而且00:00不是RTC时钟中的时间。相反,IIRC是它的父驱动程序或总线上的设备地址或“功能”;但是对此我不信任,我只记得有点模糊)。


旁注,请随时浏览此文件系统。非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中的路径,即。 e。您可以通过在sysfs挂载点前面加上前缀/sys来在普通文件空间中看到它们:

$ ls -l /sys/devices/pnp0/00:00/rtc/rtc0
$ ls -l /sys/dev/char/249:0/

这两个命令都将产生相同的输出。

一旦发出警告,与“普通”文件系统不同,sysfs会执行 硬链接目录,因此请勿尝试在其中进行任何递归搜索(例如find . /sysls -R /sys )-这些程序在与文件系统的无限循环纠缠不清之后便会崩溃。

/sys/class/rtc/rtc0/device/rtc/rtc0呢?

正如您所注意到的,从sysfs的根目录到设备参数节点有多条路径。 哪个是真正的麦考伊?

  • 并非每个设备都具有通过/dev文件系统(或其他任何设备)的接口; /dev没什么特别的-它只是一个tempfs;它是文件 /dev/rtc0,这很特殊)。这些是您无法通过路径/sys/dev/*找到的。

  • 不是每个设备都是子系统的一部分,这也是可选的。通过/sys/class*无法发现。因此,这也是一个有用但可选的链接。请注意,此节点是不同的:它必须公开子系统特定的参数。在我们的情况下,所有RTC时钟都暴露一个well-known set of settings common to the rtc sybsystem

  • 现在,/sys/devices/pnp0/00:00/rtc/rtc0 是设备sysfs节点的主要规范路径。它始终对应于其在系统总线和驱动程序层次结构中的拓扑位置:这是设备rtc0的实例rtc,在总线{{1}上的地址为00:00 }。它并不总是与其物理连接相对应。在我们的例子中,pnp0是一种虚拟总线,它不会将设备连接到物理总线和网桥,而只会发现并枚举它们。这是udev用来唯一标识它的设备的规范名称(当然没有前缀pnp0,它只是一个安装点)。

  • 最后,内核模块不必在sysfs中公开任何内容。严格来说,只有必须在用户空间中可发现的模块才需要。但是,如果这样做,该模块将确定要公开的内容,由父级和祖父母来确定sysfs中的位置,该位置将位于/sys根目录下。