macOS上的gettimeofday()是否使用系统调用?

时间:2016-12-05 05:23:39

标签: c macos time operating-system system-calls

我希望gettimeofday()会调用系统调用来完成实际获取时间的工作。但是,运行以下程序

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

int main(int argc, char const *argv[])
{
    struct timeval tv;

    printf("Before gettimeofday() %ld!\n", tv.tv_sec);

    int rc = gettimeofday(&tv, NULL);

    printf("After gettimeofday() %ld\n", tv.tv_sec);

    if (rc == -1) {
        printf("Error: gettimeofday() failed\n");
        exit(1);
    }

    printf("Exiting ! %ld\n", tv.tv_sec);
    return 0;
}
dtruss -d下的

返回一长串系统调用,最后一个是:

RELATIVE SYSCALL(args)           = return

... lots of syscalls with earlier timestamps ...

    3866 fstat64(0x1, 0x7FFF56ABC8D8, 0x11)      = 0 0
    3868 ioctl(0x1, 0x4004667A, 0x7FFF56ABC91C)      = 0 0
    3882 write_nocancel(0x1, "Before gettimeofday() 0!\n\0", 0x19)       = 25 0
    3886 write_nocancel(0x1, "After gettimeofday() 1480913810\n\0", 0x20)        = 32 0
    3887 write_nocancel(0x1, "Exiting ! 1480913810\n\0", 0x15)       = 21 0

看起来gettimeofday()没有使用系统调用,但这似乎是错误的 - 内核肯定负责系统时钟? dtruss遗失了什么吗?我是否错误地阅读了输出?

2 个答案:

答案 0 :(得分:9)

作为TheDarkKnight pointed out,系统调用 $('.pendapatan').focus(function(){ var v = $(this).val().replace(/[^0-9]/, ''); $(this).val(v); }).blur(function(){ var v = NilaiRupiah($(this).val()); $(this).val(v); }) 。但是,用户空间gettimeofday函数通常会调用相应的系统调用,而是gettimeofday,它会尝试从进程的地址空间的特殊部分读取时间称为 commpage 。仅当此调用失败时,__commpage_gettimeofday系统调用才会被用作回退。这样可以将大多数gettimeofday调用的成本从普通系统调用的成本降低到内存读取的成本。

书籍Mac OSX Internals: A Systems Approach描述了这种情况。简而言之,它是内核内存的一个特殊区域,映射到每个进程的地址空间的最后八页。除其他外,它包含“从内核异步更新并从用户空间原子读取的时间值,导致偶尔读取失败”。

为了查看用户空间函数调用gettimeofday系统调用的频率,我编写了一个测试程序,在紧密循环中调用了gettimeofday() 1亿次:

gettimeofday()

在我的计算机上的#include <sys/time.h> int main(int argc, char const *argv[]) { const int NUM_TRIALS = 100000000; struct timeval tv; for (int i = 0; i < NUM_TRIALS; i++) { gettimeofday(&tv, NULL); } return 0; } 下运行此操作表明,这会在10到20次调用dtruss -d系统调用之间触发(0.00001%-0.00002%的所有用户空间调用)。

对于有兴趣的人,source code中用户空间gettimeofday()功能(对于macOS 10.11 - El Capitan)的相关行是

gettimeofday()

函数if (__commpage_gettimeofday(tp)) { /* first try commpage */ if (__gettimeofday(tp, NULL) < 0) { /* if it fails, use syscall */ return (-1); } } combines从commpage读取的时间戳和时间戳计数器寄存器的读数,以秒和微秒计算自纪元以来的时间。 (__commpage_gettimeofday指令位于_mach_absolute_time内。)

答案 1 :(得分:1)

使用dtrace代替dtruss将清除您的怀疑。 gettimeofday()本身就是一个系统调用。如果运行dtrace脚本,则可以看到调用此系统调用。

您可以使用以下dtrace脚本 “dtrace1.d”

syscall:::entry
/ execname == "foo" / 
{
}

(foo是您的可执行文件的名称)

在dtrace上面运行使用:dtrace -s dtrace1.d

然后执行您的程序以查看程序使用的所有系统调用