移除RTC电池后hwclock与timedatectl的异常行为及技术疑问
测试环境配置
- 移除RTC电池
- 未配置NTP服务器
- 内核配置:
CONFIG_RTC_HCTOSYS=y、CONFIG_RTC_SYSTOHC=y
系统启动后命令执行结果
$ hwclock hwclock: ioctl(RTC_RD_TIME) to /dev/rtc0 to read the time failed: Invalid argument $ timedatectl Failed to query server: Failed to read RTC: Invalid argument $ date Wed Mar 24 11:26:45 CET 2021
执行hwclock -w后,三个命令均恢复正常,显示与date返回的相同时间。
技术问题解答
1. date命令返回的旧日期时间来源于何处?
这个时间是内核启动时的默认基准时间。因为开启了CONFIG_RTC_HCTOSYS=y,内核启动时会尝试从RTC读取时间同步到系统时钟,但RTC无电池供电导致内部时间无效,读取失败。此时内核会 fallback 到编译内核时的镜像构建时间,部分嵌入式平台也可能从设备树或固件中获取一个预设默认时间,这就是date返回的旧时间。
2. hwclock -w为何能解决命令报错?
hwclock -w的作用是直接把当前系统时钟(也就是date显示的时间)写入RTC设备。之前hwclock和timedatectl报错,是因为RTC内部没有有效时间数据,读取操作触发了Invalid argument错误。执行hwclock -w后,系统将合法时间写入RTC,设备内部有了可读取的有效时间记录,后续读取操作就能正常完成,所以两个命令不再报错,显示的时间和date一致——因为它们读的就是刚才写入RTC的系统时间。
你之前的误解在于,hwclock -w不需要依赖timedatectl,它直接与/dev/rtc0交互,读取内核维护的系统时钟(xtime)并写入RTC硬件,和timedatectl的状态完全无关。
3. 能否配置timedatectl,使其在移除RTC电池时像date一样返回日期时间而非报错?
不能直接通过配置timedatectl实现。timedatectl的设计逻辑是优先依赖RTC或NTP作为时间源,当RTC读取失败且无NTP可用时,它会直接报错,不会自动 fallback 到内核维护的系统时钟。
要让相关工具都正常显示时间不报错,更简单可靠的方法是在系统启动脚本中添加hwclock -w命令,让系统启动后自动把内核默认时间写入RTC,这样timedatectl和hwclock就能正常工作了。修改systemd中timedate服务配置的方式复杂度高,不推荐使用。
内容的提问来源于stack exchange,提问作者Maxim

