macOS上的gettimeofday()是否使用系统调用? [英] Does gettimeofday() on macOS use a system call?

查看:130
本文介绍了macOS上的gettimeofday()是否使用系统调用?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I expect that gettimeofday() will call a system call to do the work of actually getting the time. However, running the following program

#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 下的

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

under dtruss -d returns a long list of system calls, the last of which are:

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()不在使用syscall,但这似乎是错误的-肯定是内核由系统时钟负责吗? dtruss 是否缺少某些内容?我读取的输出不正确吗?

It looks like gettimeofday() isn't using a syscall, but this seems wrong-surely the kernel takes responsibility of the system clocks? Is dtruss missing something? Am I reading the output incorrectly?

推荐答案

作为TheDarkKnight

As TheDarkKnight pointed out, there is a gettimeofday system call. However, the userspace gettimeofday function often does not call the corresponding system call, but rather __commpage_gettimeofday, which tries to read the time from a special part of the process' address space called the commpage. Only if this call fails does the gettimeofday system call get used as a fallback. This reduces the cost of most calls to gettimeofday from that of an ordinary system call to just a memory read.

这本书

The book Mac OSX Internals: A Systems Approach describes the commpage. Briefly, it is a special area of kernel memory that is mapped into the last eight pages of the address space of every process. Among other things, it contains time values that are "updated asynchronously from the kernel and read atomically from user space, leading to occasional failures in reading".

要查看userspace函数多长时间调用一次 gettimeofday()系统调用,我编写了一个名为 gettimeofday()的测试程序,该程序紧凑地进行了1亿次循环:

To see how often the gettimeofday() system call is called by the userspace function, I wrote a test program that called gettimeofday() 100 million times in a tight loop:

#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;
}

在我的计算机上的 dtruss -d 下运行此命令显示,此操作触发了10-20次对 gettimeofday()系统调用的调用(占所有调用的0.00001%-0.00002%用户空间调用).

Running this under dtruss -d on my machine showed that this triggered between 10-20 calls to the gettimeofday() system calls (0.00001%-0.00002% of all the userspace calls).

对于那些感兴趣的人,

For those interested, the relevant lines in the source code for the userspace gettimeofday() function (for macOS 10.11 - El Capitan) are

if (__commpage_gettimeofday(tp)) {      /* first try commpage */
    if (__gettimeofday(tp, NULL) < 0) { /* if it fails, use syscall */
        return (-1);
    }
}

函数 __ commpage_gettimeofday 结合从commpage读取的时间戳和时间戳计数器寄存器的读数,以秒和微秒为单位计算自纪元以来的时间.( rdstc 指令位于

The function __commpage_gettimeofday combines the timestamp read from the commpage and a reading of the time stamp counter register to calculate the time since epoch in seconds and microseconds. (The rdstc instruction is inside _mach_absolute_time.)

这篇关于macOS上的gettimeofday()是否使用系统调用?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆