关于内核时钟,发现一个很奇怪的问题

ytfhwfnh 2020-04-26 01:55:30
因为需要封装一个类似vx的tickGet函数,我通过gettimeofday来获取时间。但考虑到这个tv_sec是个long值(在32位arm板子上用),在未来的某一刻会溢出。我就写个测试代码,想模拟一下,代码如下:

#include <stdio.h>
#include <time.h>
#include <unistd.h>
#include <sys/time.h>

int main()
{
int i;
unsigned long ret = 0;
struct timeval tv1, tv2;

tv1.tv_sec = 0x7ffffff0; // 设置系统时间,将在16秒后出现溢出
tv1.tv_usec = 0;
settimeofday(&tv1, NULL);

for (i = 0; i < 30; i++)
{
gettimeofday(&tv2, NULL);

printf("%d: sec = %ld, usec = %d\r\n", i, tv2.tv_sec, tv2.tv_usec);

ret = tv2.tv_sec * 100 + tv2.tv_usec / 10000;
printf("ret1 = %lu\r\n", ret);

ret = (long long)tv2.tv_sec * 100 + tv2.tv_usec / 10000;
printf("ret2 = %lu\r\n", ret);

ret = (tv2.tv_sec * 100 + tv2.tv_usec / 10000) & 0x7fffffff;
printf("ret3 = %lu\r\n", ret);

ret = ((long long)tv2.tv_sec * 100 + tv2.tv_usec / 10000) & 0x7fffffff;
printf("ret4 = %lu\r\n", ret);

sleep(1); // 16秒后,这里为啥会卡死?
}

return 0;
}

然后,我交叉编译放到ARM板子上去跑。前16秒结果:

0: sec = 2147483632, usec = 29
ret1 = 4294965696
ret2 = 4294965696
ret3 = 2147482048
ret4 = 2147482048
1: sec = 2147483633, usec = 9641
ret1 = 4294965796
ret2 = 4294965796
ret3 = 2147482148
ret4 = 2147482148
2: sec = 2147483634, usec = 21143
ret1 = 4294965898
ret2 = 4294965898
ret3 = 2147482250
ret4 = 2147482250
3: sec = 2147483635, usec = 24093
ret1 = 4294965998
ret2 = 4294965998
ret3 = 2147482350
ret4 = 2147482350
4: sec = 2147483636, usec = 35551
ret1 = 4294966099
ret2 = 4294966099
ret3 = 2147482451
ret4 = 2147482451
5: sec = 2147483637, usec = 47074
ret1 = 4294966200
ret2 = 4294966200
ret3 = 2147482552
ret4 = 2147482552
6: sec = 2147483638, usec = 58611
ret1 = 4294966301
ret2 = 4294966301
ret3 = 2147482653
ret4 = 2147482653
7: sec = 2147483639, usec = 70127
ret1 = 4294966403
ret2 = 4294966403
ret3 = 2147482755
ret4 = 2147482755
8: sec = 2147483640, usec = 81581
ret1 = 4294966504
ret2 = 4294966504
ret3 = 2147482856
ret4 = 2147482856
9: sec = 2147483641, usec = 93073
ret1 = 4294966605
ret2 = 4294966605
ret3 = 2147482957
ret4 = 2147482957
10: sec = 2147483642, usec = 96241
ret1 = 4294966705
ret2 = 4294966705
ret3 = 2147483057
ret4 = 2147483057
11: sec = 2147483643, usec = 107747
ret1 = 4294966806
ret2 = 4294966806
ret3 = 2147483158
ret4 = 2147483158
12: sec = 2147483644, usec = 110868
ret1 = 4294966907
ret2 = 4294966907
ret3 = 2147483259
ret4 = 2147483259
13: sec = 2147483645, usec = 122437
ret1 = 4294967008
ret2 = 4294967008
ret3 = 2147483360
ret4 = 2147483360
14: sec = 2147483646, usec = 125615
ret1 = 4294967108
ret2 = 4294967108
ret3 = 2147483460
ret4 = 2147483460
15: sec = 2147483647, usec = 137135
ret1 = 4294967209
ret2 = 4294967209
ret3 = 2147483561
ret4 = 2147483561

但是,跑到这里程序就卡死了。我再怎么等待,也没有响应。再开一个终端,查看系统时间已变成“Fri Dec 13 20:45:57 UTC 1901”,系统时间依然在增加。
我的问题是,sleep为啥会卡死?这样的话,这个板子上凡是用到sleep的地方,在2038年的某一天,统统会卡死?这是多么严重的bug,不可接受啊。
对了,linux内核版本是3.10.0。
交叉编译前缀arm-none-linux-gnueabi-

另外,系统自举后,系统时间是1970-1-1。设置tv_sec = 0x7ffffff0,等16秒溢出后,系统时间变成1901年10月13,难道是因为tv_sec变为了负数?
...全文
751 点赞 收藏 3
写回复
3 条回复
ytfhwfnh 2020年05月05日
引用 2 楼 bo_self_effacing 的回复:
我觉得吧,如果你的程序一定得以现在的代码就兼容2038年后的状况,就需要考虑其他手段来规避这种系统问题,而不用纠结现在的操作系统不支持这种状况。

嗯嗯,后来百度才知道,这是32位linux的一个bug。sleep没法用,解决不了,但封装自动环绕的tick程序没有问题。
回复 点赞
bo_self_effacing 2020年05月02日
我觉得吧,如果你的程序一定得以现在的代码就兼容2038年后的状况,就需要考虑其他手段来规避这种系统问题,而不用纠结现在的操作系统不支持这种状况。
回复 点赞
ytfhwfnh 2020年04月26日
系统卡死之前的时间是“Tue Jan 19 03:14:06 UTC 2038”,大家如果有条件,可以手动设置时间然后等几秒试试。
回复 点赞
发动态
发帖子
Linux_Kernel
创建于2007-08-27

3147

社区成员

1.7w+

社区内容

Linux/Unix社区 内核源代码研究区
社区公告
暂无公告