有没有办法在Linux中的32位程序中获取64位time_t?

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

在 Windows 上我可以调用:

_time32(__time32_t); // to get 32-bit time_t
_time64(__time64_t); // to get 64-bit time_t

(32 位和 64 位程序)

有什么办法在Linux中做到这一点(用GCC编译)?

c linux gcc 64-bit time-t
5个回答
18
投票

上面很多答案都说这是不可能的,但这是完全错误的。当时“这是不可能的”,但人们多年来一直在“谈论修复它”。最后,32 位平台上的 64 位时间支持被引入到 Linux 5.1 内核,并添加了新的 *time64 系统调用。查看此表

,您可以看到这些系统调用仅在 32 位平台上可用。现在,如果您正在为 32 位系统编写代码,您可以直接调用 
clock_gettime64(通过内联汇编或带有 syscall()
 的 C)来获取当前时间
但是之后你就完全靠自己了。如果您想要完整的
userspace
支持,您必须使用Linux 5.6或更高版本以及musl 1.2+或glibc 2.32+。只需重建你的代码,你的

time_t

就会变成64位长

所有用户空间都必须使用 64 位
time_t
    进行编译,即将推出的 musl-1.2 和 glibc-2.32 版本以及 linux-5.6 或更高版本中安装的内核头文件将支持该版本。
  • 直接使用系统调用接口的应用程序需要移植以使用linux-5.1中添加的

    time64
  • 系统调用来代替现有的系统调用。这会影响
  • futex()

    seccomp()
    的大多数用户以及拥有自己的运行时环境但不基于 libc 的编程语言。
    
    

    https://lkml.org/lkml/2020/1/29/355?anz=web

不幸的是,正如 Debian 在过渡时所说的那样

你可能仍然需要在各种情况下构建自己的库

glibc 2.34 支持现有的 32 位 ABI/API 和新的 64 位 ABI/API。但是,它不提供强制使用新 API/ABI 的开关 - 每个构建/包都明确选择使用 64 位 API/ABI(通过设置 _TIME_BITS=64

)。这对于 Debian 来说是一个问题,因为在正常的过渡中,我们期望简单地针对新库进行构建就能获得新的 ABI。有些东西(glibc、dpkg、gcc?)必须说“默认使用 64 位时间”。
1030159

已实现

DEB_BUILD_OPTIONS=abi=+time64
选项作为一致的 Debian 机制。
欲了解更多信息

接近2038年内核终局游戏

time()

14
投票
time32()

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 位:
(

Source

)
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 位值,也不会改变任何事情。

您可以将您的应用程序深深地绑定到内核中,但我认为这根本不值得。

标准库中未包含 

time64()/time32()

函数。


7
投票
time32_t/time64_t

定义。


time_t

定义为

time.h

typedef __time_t time_t

;


经过一长串的重新定义,您会发现
__time_t
在 32 位机器上被定义为 32 位,在 64 位机器上被定义为 64 位。
    

使用此库:

https://github.com/evalEmpire/y2038


1
投票
该项目的目标是提供 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)); } }

-4
投票
get_mytime64()

如果您不关心溢出问题,由于 C 的隐式数字转换,一个简单的 
return time(NULL);

对这两个函数都适用。

    

© www.soinside.com 2019 - 2024. All rights reserved.