嵌入式Linux(32位)的2038年解决方案是什么?

26

如何在32位嵌入式Linux(ARMLinux)的C代码中处理时间,以确保代码在2038年1月19日03:14:07 UTC之后(即有符号32位time_t溢出时)仍能正常工作?考虑到系统上的time_t是有符号32位的,那么有哪些替代方案呢?

大量的搜索未发现实用的解决方法。每个人似乎都假定到那时我们都将使用64位操作系统,但显然嵌入式系统不是这样。

在我需要使用的系统上,__kernel_time_t被定义为long。这可能意味着没有内核支持64位时间。uClibc的版本为0.9.29。

我不相信我是唯一面临此问题的人,也不想重新发明轮子。


1
尽管我认为这是一个好问题,但它可能对于SO来说太宽泛了。您是否搜索过LKML或发布请求? - too honest for this site
4
在嵌入式领域,20年并不算太长。我工作的某个系统已经超过35年了。 - Ian Goldby
1
@n.m.:令人惊讶的是,有些应用领域并不每年都会推出新设备。例如家用电器,比如洗衣机(当然不包括廉价款式)等。 - too honest for this site
你是指35年的物理安装还是35年的软件?前者无论如何都必须在2038年之前更换/更新。对于后者,目标CPU的字长是无关紧要的。使用支持64位time_t(或time64_t)的操作系统/编译器/标准库组合。如果您没有选择该组合,请以书面形式向负责人报告问题,然后继续前进。您无法解决所有问题。 - n. m.
1
2021年问候!Linux 5.6及以上版本已准备好在32位系统上运行到2038年以后:https://lkml.org/lkml/2020/1/29/355?anz=web - Emile Cormier
显示剩余9条评论
3个回答

10

没有银弹、技巧或聪明的解决方案。要么使用具有64位time_t的操作系统,否则不要使用time_t及其依赖的任何操作系统功能(这包括文件系统、定时器、网络等等),或者计划在未来20年内更新软件。

至少有两个类Unix系统在32位机器上支持64位的time_t:OpenBSD和NetBSD。OpenBSD有一些关于此背后原理的演讲:http://www.openbsd.org/papers/eurobsdcon_2013_time_t/index.html


1
我将此标记为答案,仅仅是因为我们最终的决定是暂时使用32位时间,并且稍后再考虑这个问题。在我看来,这不是一个很好的解决方案,但我正在处理的组件并不是唯一受影响的组件。 - Ian Goldby
由于ARMLinux似乎基于NetBSD,因此您可以使用32位版本而不必担心。但请在源代码中进行检查。认为2038年遥远并不奇妙,因为它距离现在不到18年。 - theking2
1
2021年问候!Linux 5.6及以上版本已准备好在32位系统上运行到2038年以后:https://lkml.org/lkml/2020/1/29/355?anz=web - Emile Cormier

8
时间转换程序可以使用2038年1月19日03:14:07Z作为Unix纪元时间的基准,如果时间戳低于某个值。
即使您的系统在2010年01月01日投入生产,您也可以假设没有溢出的时间戳低于1262300400(该日期的Unix纪元时间)。
如果遇到较低的时间戳,请考虑它已经溢出,并使用2038年1月19日03:14:07Z作为基础时间。比较也必须考虑在内。
这不是一个干净的解决方案,但需要适度的努力。最好切换到64位时间戳(顺便说一句,这并不绝对需要64位系统)。

2
这是一个非常糟糕的方法。在我的Linux系统上,有相当多的文件时间戳是1999年左右。此外,当您提取从其他地方获取的存档(例如来自软件包更新)时,修改时间可能会出现问题。 - fuz
5
我会尽力进行翻译。@FUZxxl 我同意 ;) 但我们现在谈论的是嵌入式系统,影响可能是可以控制的。 - Ctx
不合理的未来时间戳可能会产生致命影响。例如,它会完全扰乱基于时间戳操作的make或备份程序。 - fuz
@FUZxxl:我绝对不想在那个日期旅行:飞机、火车和汽车...可能都会是自动驾驶的,但很可能无法免于“千年虫”母亲级别的错误。 - chqrlie
1
这很巧妙,但可能有点过于聪明了。对于那些需要在你之后维护系统的人来说,这肯定会是一个有趣的惊喜。这是你的接替者未来在 Stack Overflow 上发帖的预示吗? - Zhro
新纪元是2106-02-07T06:28:16Z(Unix纪元+ 2 ^ 32秒)。2038年日期是符号位翻转的时间点。 - Edgar Bonet

4
我假设您的嵌入式系统ABI将“long”定义为32位。
“time_t”类型没有要求必须是有符号的。您是否可以将其更改为“unsigned long”,并为自己和您的后代多获得68年的宁静?更改此内容需要重新编译内核、C库以及所有使用“time_t”的程序和库...这不是一项轻松的任务!您可能也可以将其定义为“long long”,但这将更改许多结构布局,难度更大。

3
如果你不介意重新编译整个系统上的每个二进制文件,为什么不直接升级呢? - cat
2
@cat:好观点!如果OP对系统软件栈有足够的控制权,他有几个选项可以防止这个问题,升级比使用内核类型进行修补要好得多,如果没有,那么就没有太多可以做的了。 - chqrlie

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接