1970年是Unix系统诞生年,因此1970年被定义为Unix或类Unix系统的元纪。所有系统都以1970年1月1日 0点0分0秒作为时间的基准点,用秒数来表示系统时间,也即当前系统时间是从基准时间(1970年1月1日 0点0分0秒)走过多少秒之后的时间。
用简单公式来表即:系统时间 = 基准时间 + 秒数
在POSIX标准中,将表示秒数的类型定义为time_t,而它是32位有符号整数类型。
下面是秒数与绝对时间的对照表:
time_t类型的秒数值 系统时间(绝对时间)
0 1970-01-0100:00:00
1 1970-01-0100:00:01
0x7ffffffff2038-01-1903:14:07
在32位系统上,time_t能表示的最大值为0x7ffffffff,当time_t取最大值时表示系统时间为2038-01-19 03:14:07,但时间再往后走时,那time_t会溢出变成一个负值,此时系统时间会倒流回到1901年,届时操作系统和上层软件都会运行错出。
大部分64位操作系统已经把time_t这个系统变量改为64位宽。不过,其他现有架构的改动仍在进行中,不能抱有 “应该可以在2038年前完成”所有32位系统的改造幻想。因此,linux社区已经在5.6版本将2038问题解决了,今天我们着重分析5.6版本是如何解决2038问题的。
虽然5.6版本正式公布解决了2038问题,但实际解决这个问题过程已经持续了好多年。从git log可以查看变更信息
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/log/
要彻底解决2038问题,需要从以下几个部分入手:
1、用户态glibc对64位新型time_t以及相应函数的支持
2、内核态对64位新型time_t以及系统调用实现的支持
3、文件系统解决2038年问题
从社区代码看,一方面是将32位的变量和函数转换成64位,另一方面是定义了新的数据结构进行转换,例如struct__kernel_timex_timeval、time64_t、ktime_to_timespec64()
总结一下:2038年问题与之前的千年虫问题的杀伤力是不一样的,千年虫属于应用程序的问题,而2038年问题却是系统级的,有更大的杀伤力。不过社区已经提前近20年解决了这个问题,之所以这么提前也是因为有了前车之鉴,存在的隐患尽早发现,尽早解决。