如何在没有操作系统的 32 位嵌入式系统上修复 ANSI C 中的 Y2036 NTP 问题

问题描述 投票:0回答:1

随着 2036 年缓慢(但不可避免)的临近,我们对 SNTP 时间同步算法感到担忧,该算法现在非常简单:

// NTP structure received in udp_data_buffer
uint32_t ntpStamp = ntohl(&((uint8_t *)udp_data_buffer)[0x28]);
time_t unixTime = ntpStamp - 2208988800U;
struct tm * buf;
buf = localtime(&unixTime);
uint16_t year = (uint16_t)(buf->tm_year + 1900);
uint8_t month = (uint8_t)(buf->tm_mon + 1);
uint8_t day = (uint8_t)buf->tm_mday;
uint8_t hour = (uint8_t)buf->tm_hour;
uint8_t min = (uint8_t)buf->tm_min;
uint8_t sec = (uint8_t)buf->tm_sec;
// now sync the RTC chip

硬件平台为Cortex M3 32位(NXP redlib),未使用标准操作系统。

time_t 类型在 libconfig-arm.h 中有以下声明:

typedef unsigned int time_t;     /* date/time in unix secs past 1-Jan-70 */

问题是如何让这个解决 2036 年(也许还有 2038 年)问题?

据我从 NTP 规范了解。它不直接支持任何可用的东西:

https://datatracker.ietf.org/doc/html/rfc5905

Eras不能直接由NTP产生,也不需要做 所以。必要时,它们可以从外部手段获得,例如 作为文件系统或专用硬件。

嗯,这是我不舒服的说法。怎么可能没有必要这样做呢?为什么时代也没有传播呢?如果是的话,就不需要像下面这样的“黑客”了:

https://datatracker.ietf.org/doc/html/rfc2030

由于 NTP 时间戳格式已使用了 17 年, 40年后仍有可能使用 当秒字段溢出时。因为这可能是不合适的 为了在 1968 年设置位 0 之前存档 NTP 时间戳, 延长 NTP 时间戳使用寿命的便捷方法是 以下约定:如果设置了位 0,则 UTC 时间位于 范围 1968-2036,UTC 时间从 0h 0m 0s UTC on 1 开始计算 1900 年 1 月。如果未设置位 0,则时间范围为 2036- 2104 和 UTC 时间从 2 月 7 日 6h 28m 16s UTC 开始计算 2036.注意计算对应关系时,2000不是一个 闰年。另请注意,闰秒不计入 算账。

这意味着即使有这个“黑客”,NTP也会结束2104。并不是我个人关心2104,但它不是一个普遍适用的解决方案。

这里使用的示例: https://commons.apache.org/proper/commons-net/javadocs/api-1.4.1/src-html/org/apache/commons/net/ntp/TimeStamp.html

(尼特注释:赋值uint16_tyear = (uint16_t)(buf->tm_year + 1900);在非常遥远的Y65536问题方面也有错误,但这是所使用的RTC芯片的限制,我无法更改.)

c ntp rfc
1个回答
0
投票

NTP 的时间必须大于编译时间,因为您的软件将在编译后运行。选择当前纪元,检查时间是否大于它。如果不是,则表示翻车了。

uint64_t unixTime = ntpStamp - 2208988800U;
const uint64_t NUMBER_OF_SECONDS_NOW = 1715711202;
if (unitTime < NUMBER_OF_SECONDS_NOW) {
   unixTime += UINT32_MAX;
}

滚动您自己的本地时间实现或使用正确处理 64 位时间的本地时间替代实现。嵌入式 C 标准库的一种流行实现是 Newlib https://github.com/reswitched/newlib/blob/76f6d4e21ed5b621adb75fe99a69704dca831177/newlib/libc/include/sys/_types.h#L192 。请注意,无论如何,

localtime
都会错误,因为无论如何你都无法提前知道UTC闰秒。

struct tm * buf;
buf = fixed_implementation_of_localtime(&unixTime);
© www.soinside.com 2019 - 2024. All rights reserved.