我正在研究一些Beagle Bone Black (BBB)板上的一种非常奇怪的效果。我们看到系统时钟偶尔会出现几个月的跳跃,这总是与systemd-timesyncd
更新系统时钟相关。我们每周会在不同地点的 2000 台设备中看到其中的 2 到 3 台。
我们花了很多时间检查 SNTP,但它似乎表现正常。
我们终于想出了一个板载实时时钟的硬件问题,它可能会由于电子噪声而导致它随机跳跃 131072 秒(36 小时)。这并不立即正确,报告的时间跳跃非常具体,比我们观察到的要少得多,但是对这个问题的深入阅读表明跳跃可能更加随机,甚至可能倒退。
我的问题是...... linux如何使用实时时钟来维护系统时钟?
我想知道实时时钟的错误是否只会在时间同步代理(ntpd 或 systemd-timesyncd)更新时出现在系统时钟中。系统时钟和 RTC 之间是否有任何直接联系,还是仅由代理使用?
注意:在第一段中,我提到我们看到系统时钟出现几个月的跳跃,这总是与systemd-timesyncd
更新系统时钟相关。我的意思是时间跳转后的第一条系统日志消息是Time has been changed
系统日志消息:
grep 'Time has been changed' /var/log/syslog
Oct 2 23:53:33 hostname systemd[1]: Time has been changed
Nov 21 00:07:05 hostname systemd[1]: Time has been changed
Nov 21 00:05:17 hostname systemd[1]: Time has been changed
Nov 21 00:03:29 hostname systemd[1]: Time has been changed
Nov 21 00:01:43 hostname systemd[1]: Time has been changed
Oct 3 02:07:20 hostname systemd[1]: Time has been changed
Oct 3 06:37:04 hostname systemd[1]: Time has been changed
据我所知,唯一发出这些消息的是 systemd-timesycnd (参见源代码)。显然,如果其他人知道systemd
与这些匹配的其他常规系统日志消息,我愿意接受建议。
我可以回应其中的一些观点,包括标题。
实际上,这条消息并没有告诉你是什么程序导致了时间跳跃。这只是时间跳跃的一个症状。
当内核告诉
systemd
时钟已更改时会发生这种情况。[*]systemd
通过将此消息写入系统日志来响应,然后重新计算何时.timer
需要触发任何单元。该消息由程序打印
systemd
,而不是由systemd-timesyncd
.更具体地说,消息前缀“systemd[1]:”表示它来自进程 ID 1。PID 1 是特殊的“init”进程。
systemd
systemd 项目也将其称为“系统管理器”,以将其与管理用户服务的实例区分开来。系统启动完成后,调用的程序
systemd
不会更改时钟。在您链接到的当前 systemd 源代码树中,唯一甚至读取 RTC/硬件时钟/hwclock 的程序是
timedated
,并且只有当您使用timedatectl
.我记得,旧版本的
systemd
程序在启动时读取 hwclock 一次,然后再运行任何其他程序,并相应地设置系统时钟。在最新版本中,systemd
不这样做。告诉内核哪个时区用于硬件时钟只有一些技巧。(并避免触发非常具体的称为“时间扭曲”的东西)。换句话说, current
systemd
似乎隐含地假设其他东西初始化了系统时钟。在大多数情况下,这将是内核。查找内核构建选项“在启动和恢复时从 RTC 设置系统时间” -
CONFIG_RTC_HCTOSYS
。为了全面了解,请注意还有一个选项“根据 NTP 同步设置 RTC 时间” -
CONFIG_RTC_SYSTOHC
。[*] 使用 Linux 特定功能检测系统时钟变化。见
TFD_TIMER_CANCEL_ON_SET
。非常感谢 sourcejedi 的回答。这真的让我找到了正确的答案。
回答问题
它只这样做一次,在引导期间。在下次重新启动之前,它不会再次查询 RTC。这是可配置的,但默认情况下会在大多数内核构建中这样做。
除非系统重新启动,否则 RTC 中的时间根本不可能进入系统时钟。一些代理
ntpd
可以配置为使用 RTC 作为时间源,但默认情况下通常不启用。除非您知道 RTC 是一个非常好的时间源,否则不建议启用它。看来时间是以另一种方式复制的。RTC 会定期更新系统时间。根据 sourcejedi 的回答,如果设置了CONFIG_RTC_HCTOSYS ,则这是由内核完成的。
这可以测试:
设置实时时钟
然后每隔几分钟检查一次 RTC 时间:
这样做的结果将是系统时间根本不会改变,而 RTC 最终将恢复为系统时间。
时间的原因在BBB上跳跃
正如 sourcejedi 指出的那样,消息不是由
systemd-timesyncd
. 他们被触发了connman
。证据是(应该是)虚假的日志消息/var/log/syslog
:在 1.37 版本之前,connman 被硬编码以随机轮询默认网关。它不需要配置 DHCP 来执行此操作,如果 connman 的 NTP 客户端已启用(默认情况下),那么无论任何其他配置如何,它都会执行此操作。
在我们的案例中,一些家庭路由器实际上正在响应这些 NTP 请求,但结果非常不可靠。尤其是在路由器重启的地方,它在实际上不知道正确时间的情况下继续分配时间。
例如,我们知道至少有一个版本的BT Home Hub 5在重新启动时会默认为 2018 年 11 月 21 日,并通过 NTP 给出这个日期。然后它自己的 NTP 客户端将纠正问题,但有一个窗口在 2018 年 11 月 21 日发布。
也就是说,这个问题最终是由于我们的客户重新启动了他们的路由器而 connman 只是接受了这次。
我将在这里表达我的挫败感,似乎某些人的好战已经在 connman 中留下了这个“功能”太久了。 早在 2015 年就被报告为一个问题。这是一个非常隐藏的“功能”。没有配置时间服务器,也没有日志消息来解释 connman 正在做什么或文档说明原因。如果您的测试设备在默认网关上没有 NTP 服务器,您将永远不会在测试中看到这一点。
怎么修
我们正在研究两个似乎都有效的选项:
完全删除 connman。没有它,网络似乎工作得很好;我们还没有找到它存在的原因。
在 connman 中通过编辑禁用 NTP
/var/lib/connman
以包括: