在 Windows 上,我可以调用:
_time32(__time32_t); // to get 32-bit time_t
_time64(__time64_t); // to get 64-bit time_t
(在 32 位和 64 位程序中)
在 Linux 中有什么方法可以做到这一点(用 GCC 编译)?
显然,不,这是不可能的。对于初学者来说,Linux 中只有一个time()
函数,notime32()
或time64()
.
搜索了一会,发现不是libc的错,而罪魁祸首其实是内核。
为了让 libc 获取当前时间,它需要对其执行系统调用:(Source)
time_t time (t) time_t *t;
{
// ...
INTERNAL_SYSCALL_DECL (err);
time_t res = INTERNAL_SYSCALL (time, err, 1, NULL);
// ...
return res;
}
系统调用定义为:(Source)
SYSCALL_DEFINE1(time, time_t __user *, tloc)
{
time_t i = get_seconds();
// ...
return i;
}
该函数get_seconds()
返回一个unsigned long
,如下所示:(Source)
unsigned long get_seconds(void)
{
struct timekeeper *tk = &timekeeper;
return tk->xtime_sec;
}
而且timekeeper.xtime_sec
实际上是 64 位的:(来源)
struct timekeeper {
// ...
/* Current CLOCK_REALTIME time in seconds */
u64 xtime_sec;
// ...
}
现在,如果你知道你的 C,你就知道它的大小unsigned long
实际上是依赖于实现的。在我这里的 64 位机器上,它是 64 位的;但在我这里的 32 位机器上,它是 32 位的。在某些 32 位实现上可能是 64 位,但不能保证。
另一方面,u64
它始终是 64 位的,因此在最基础上,内核以 64 位类型跟踪时间。为什么它会继续将它作为一个unsigned long
不保证为 64 位长的 .
最后,即使 libc 强制time_t
保存 64 位值,它也不会改变任何事情。
您可以将您的应用程序深深地绑定到内核中,但我认为这甚至不值得。
上面的许多答案都说这是不可能的,但这完全不正确。当时这是不可能的,但人们多年来一直在谈论修复它。最后,Linux 5.1 内核引入了32 位平台上的 64 位时间支持,并添加了新的*time64
系统调用。查看此表,您可以看到这些系统调用仅在 32 位平台上可用。现在,如果您正在为 32 位系统编写代码,您可以clock_gettime64
直接调用(从内联汇编或 C with syscall()
)来获取当前时间
然而,在那之后你就完全靠自己了。如果您想要完整的用户空间支持,您必须使用 Linux 5.6 或更高版本以及 musl 1.2+ 或 glibc 2.32+。只需重建您的代码,您的代码time_t
将变为 64 位长
所有用户空间都必须使用 64 位编译,
time_t
即将到来的 musl-1.2 和 glibc-2.32 版本以及已安装的 linux-5.6 或更高版本的内核头文件将支持该版本。直接使用系统调用接口的应用程序需要移植以使用
time64
linux-5.1 中添加的系统调用来代替现有的系统调用。这会影响大多数用户futex()
以及seccomp()
拥有自己的运行时环境而不基于 libc 的编程语言。
了解更多信息
标准库中不包含任何time64()/time32()
功能。
标准头文件中不考虑任何time32_t/time64_t
定义。
time_t
定义time.h
为typedef __time_t time_t
;
经过一长串的重新定义,您会发现__time_t
在 32 位机器上定义为 32 位,在 64 位机器上定义为 64 位。
使用这个库:https ://github.com/evalEmpire/y2038
该项目的目标是为 POSIX time.h 提供一个替代品,它可以在具有 32 位 time_t 的机器上工作,但不会受到 2038 错误的影响。这将允许 C 程序员在 2038 年安全,而无需将他们的软件重写为新接口。它在仍然使用系统时区数据库的同时执行此操作。
如果你真的需要这个,为什么不自己动手呢?
typedef int32_t my_time32;
typedef int64_t my_time64;
my_time32 get_mytime32() {
if (sizeof(time_t) == sizeof(my_time32))
return time(NULL);
else {
/* Check for overflow etc. here... */
return (my_time32)(time(NULL));
}
}
同样对于get_mytime64()
.
如果您不关心溢出,return time(NULL);
由于 C 的隐式数字转换,一个简单的函数对这两个函数都有效。