【问题标题】:How do I find which RTC module my kernel loads?如何找到我的内核加载的 RTC 模块?
【发布时间】:2017-12-22 11:28:35
【问题描述】:

在使用从 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 也没有提供太多信息。

低级检查,显示设备存在:

$ 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

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

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

【问题讨论】:

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


    【解决方案1】:

    我知道 OP 得到了狭义问题的正确答案,但我觉得更具有概括答案的精神,所以我发布它希望对回答概括问题有所帮助:如何找到/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 用于字符设备,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 没有什么特别之处——它只是一个临时文件;它是 文件 @987654350 @ 这是特别的)。这些你不会通过路径/sys/dev/* 找到。

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

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

    • 最后,内核模块不必在 sysfs 中公开任何东西。严格来说,只有必须从用户空间发现的模块才需要它。但如果是这样,则模块决定 什么 公开,它的父级和祖父母级确定 where 在 sysfs 中它将位于 devices 根目录下。

    【讨论】:

      【解决方案2】:

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

      没错,如果您只关心那个 RTC,那么 rtc_cmos 就是您所需要的。 如果您的 PC 足够新,rtc-efi 可能是一个有效的替代方案。

      还有,为什么 modinfo rtc_cmos 什么都不返回?

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

      【讨论】:

      • 是的! $ grep CMOS /usr/src/linux/.config CONFIG_GENERIC_CMOS_UPDATE=y CONFIG_RTC_DRV_CMOS=y
      • rtc-efi 是 efi 模块的一部分吗?我看到了CONFIG_EFI=y,但我没有看到grep CONFIG_RTC /usr/src/linux/.config | grep -i EFI 的任何内容
      • 好的,感谢您告诉我。所以,这意味着我的内核正在使用 GENERIC_CMOS 驱动程序。我重新编译了我的内核并取消标记其他驱动程序,到目前为止计算机按预期工作。
      猜你喜欢
      • 2013-03-10
      • 2014-01-06
      • 1970-01-01
      • 2021-12-22
      • 1970-01-01
      • 2012-08-20
      • 2016-01-05
      • 1970-01-01
      • 2012-03-14
      相关资源
      最近更新 更多