回答问题

回答问题

我正在调查对某些人的一种非常奇怪的影响比格犬骨黑色 (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这些消息匹配的其他常规系统日志消息,我愿意接受建议。

答案1

我可以回应其中一些观点,包括标题。

[...]这始终与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

实际上,这条消息并没有告诉你是什么程序导致了时间跳跃。这只是时间跳跃的一个症状。

当内核告知systemd时钟已更改时,就会发生这种情况。[*]systemd通过将此消息写入系统日志进行响应,然后重新计算何时.timer需要触发任何单元。

该消息是由程序打印的systemd,而不是由systemd-timesyncd.

更具体地说,消息前缀“systemd[1]:”表示它来自进程 ID 1。PID 1 是特殊的“init”进程。 systemd 项目也将其称为“系统管理器”,以区别于systemd管理用户服务的实例。


systemd系统完成启动后,调用的程序不会更改时钟。

在您链接到的当前 systemd 源代码树中,唯一读取 RTC/硬件时钟/hwclock 的程序是timedated,并且仅当您使用 查询它时timedatectl

我记得,该systemd程序的旧版本在启动时读取 hwclock 一次,然后再运行任何其他程序,并相应地设置系统时钟。在最新版本中,systemd没有这样做。只有一些黑客告诉内核哪个时区用于硬件时钟。 (并避免触发一些非常具体的东西,称为“时间扭曲”)。

换句话说,currentsystemd似乎隐含地假设其他东西初始化了系统时钟。在大多数情况下,这将是内核。

查找内核构建选项“启动和恢复时从 RTC 设置系统时间”- CONFIG_RTC_HCTOSYS

为了全面理解,请注意还有一个选项“根据 NTP 同步设置 RTC 时间”- CONFIG_RTC_SYSTOHC


[*] 使用 Linux 特定功能检测系统时钟更改。看TFD_TIMER_CANCEL_ON_SET

答案2

非常感谢sourcejedi这个答案。这确实让我找到了正确的答案。

回答问题

Linux如何使用实时时钟来维护系统时钟?

它只在启动期间执行一次。在下次重新启动之前,它不会再次查询 RTC。这是可配置的,但在大多数内核版本中默认都会这样做。


我想知道当时间同步代理(ntpd 或 systemd-timesyncd)更新时,实时时钟的错误是否只会出现在系统时钟中。

除非系统重新启动,否则 RTC 中的时间根本不可能进入系统时钟。有些代理喜欢ntpd可以配置为使用 RTC 作为时间源但这通常不是默认启用的。除非您知道 RTC 是一个非常好的时间源,否则不建议启用它。


系统时钟之间有直接联系吗?

看来时间是以另一种方式复制的。 RTC 会定期更新系统时间。根据sourcejedi的回答,这是由内核完成的,如果配置_RTC_HCTOSYS已设置。

可以这样测试:

  • 设置实时时钟

    # hwclock --set --date='18:28'
    
  • 然后每隔几分钟检查 RTC 时间:

    # hwclock
    

这样做的结果将是系统时间根本不会改变,RTC最终将恢复为系统时间。


BBB时间跳跃的原因

正如 Sourcejedi 指出的那样,这些消息不是由 触发的systemd-timesyncd。他们被触发了connman。证据是(应该)虚假日志消息/var/log/syslog

Oct  3 00:10:37 hostname connmand[1040]: ntp: adjust (jump): -27302612.028018 sec
...
Nov 21 00:07:05 hostname systemd[1]: Time has been changed

1.37 之前的版本、 connman 被硬编码以混杂轮询默认网关的时间。如果启用了 connman 的 NTP 客户端,则无需配置 DHCP 即可执行此操作(默认)那么无论任何其他配置如何,它都会执行此操作。

在我们的例子中,一些家庭路由器实际上响应了这些 NTP 请求,但结果非常不可靠。特别是在路由器重新启动的情况下在实际上不知道正确时间的情况下继续分发时间

例如,我们知道至少有一个版本英国电信家庭中心 5重新启动后,将默认为 2018 年 11 月 21 日,并通过 NTP 给出该日期。然后,它自己的 NTP 客户端将纠正问题,但有一个窗口显示 2018 年 11 月 21 日。

也就是说,这个问题最终是由于我们的客户重新启动他们的路由器而 connman 这次只是接受而引起的。

我将在这里表达我的沮丧,似乎某些人的好战性已经在 connman 中留下了这个“功能”太久了。 早在 2015 年就被报告为一个问题。这是一个隐藏得很好的“功能”。没有配置时间服务器,也没有日志消息来解释 connman 正在做什么,也没有文档说明原因。如果您的测试设备的默认网关上没有 NTP 服务器,您将永远不会在测试中看到这一点。


怎么修

我们正在研究两个似乎都有效的选项:

  1. 完全删除 connman。看起来网络在没有它的情况下也能正常工作;我们还没有找到它存在的原因。

    apt-get remove connman
    
  2. /var/lib/connman通过编辑以包括以下内容来禁用 connman 中的 NTP :

    [global]
    TimeUpdates=manual
    

相关内容