【问题标题】:How to get the true value of the system clock in raw ticks (i.e. mach_absolute_time) in a x86_64 process running under Rosetta 2?如何在 Rosetta 2 下运行的 x86_64 进程中以原始刻度(即 mach_absolute_time)获取系统时钟的真实值?
【发布时间】:2021-09-24 16:48:03
【问题描述】:

我正在编写一个 macOS x86-64 应用程序,由于仅 x86-64 的库依赖关系,该应用程序目前无法编译为通用二进制文件。

此应用需要与在 Apple Silicon mac 上作为 arm64 运行的其他进程进行交互,并且在此过程中它需要以原始滴答数获取系统时钟的值,这将由 mach_absolute_time() 返回。

但是,在 Apple Silicon mac 上,mach_absolute_time() 在从本机 arm64 应用程序调用和从 Rosetta 2 下的 x86-64 应用程序调用时具有不同的行为。

在 Intel mac 上,mach_absolute_time() 返回以纳秒为单位的系统时钟,mach_timebase_info() 返回 1:1 的纳秒与时钟滴答比。

在 Apple Silicon mac 上,系统时钟的单位不再以纳秒为单位,因此mach_timebase_info() 不会返回 1:1 的比率。 (在我的 M1 Mac Mini 上,我得到 125:3 的比率。)

但是,在 Rosetta 2 下运行的 x86-64 应用程序将获得与在英特尔处理器上相同的值,即 1:1 的比率,mach_absolute_time() 返回以纳秒为单位的值。

这对我来说是个问题,因为我需要我的 x86-64 应用程序来获取 mach_absolute_time() 的实际值,就好像它是从 arm64 进程调用的一样。

到目前为止,我还没有找到一种方法来做到这一点。我知道的每个与时钟相关的函数在 Rosetta 2 下调用时都会返回“假”值。我能想到的唯一解决方案是将作为通用二进制文件的可执行文件捆绑到我的应用程序中,从我的应用程序调用它,拥有它获取作为 arm64 本地运行的时基信息,并将值传回。但这比我想要的解决方案要重得多。

有没有办法在 Rosetta 2 下运行的 x86-64 应用程序中获取真正的系统时钟时基?

【问题讨论】:

    标签: macos time system-clock rosetta-2


    【解决方案1】:

    我找到了一种方法,但它并不完美。当运行在 Rosetta 中的 x86_64 应用程序执行以下函数时,将返回与 arm64 应用程序 mach_absolute_time() 相同的时间:

    uint64_t machAbsoluteTimeFromSysctl()
    {
        uint64_t vals[2];
        size_t size = sizeof(vals);
        
        if (sysctlbyname("kern.monotonicclock_usecs", &vals, &size, NULL, 0) == -1) {
            printf("Error: sysctl kern.monotonicclock_usecs failed with error: %d\n", errno);
            return mach_absolute_time();
        }
        
        return vals[1];
    }
    

    由于这是使用 sysctl,因此需要花费大量时间来获取时间戳(尽管仍不到一毫秒),这对于计时功能来说是不幸的,但对于我的目的来说似乎已经足够了。

    我将不将此答案标记为已接受的答案,以防其他人提出更好的方法。

    【讨论】:

      猜你喜欢
      • 2014-01-16
      • 1970-01-01
      • 2010-11-06
      • 1970-01-01
      • 1970-01-01
      • 2021-03-01
      • 1970-01-01
      • 2021-03-28
      • 1970-01-01
      相关资源
      最近更新 更多