为什么来自 time.h 的 time() 没有对 sys_time 的系统调用?

Why doesn't time() from time.h have a syscall to sys_time?

我写了一个非常简单的程序,调用 time() 来说明 strace 的用法,但我遇到了问题; time() 调用似乎实际上并没有产生系统调用!

我最终进入了 GDB 中的 time() 函数,现在我比以往任何时候都更加困惑。来自 time() 函数的反汇编:

0x7ffff7ffad90 <time>:  push   rbp
0x7ffff7ffad91 <time+1>:    test   rdi,rdi
0x7ffff7ffad94 <time+4>:    mov    rax,QWORD PTR [rip+0xffffffffffffd30d]        # 0x7ffff7ff80a8
0x7ffff7ffad9b <time+11>:   mov    rbp,rsp
0x7ffff7ffad9e <time+14>:   je     0x7ffff7ffada3 <time+19>
0x7ffff7ffada0 <time+16>:   mov    QWORD PTR [rdi],rax
0x7ffff7ffada3 <time+19>:   pop    rbp
0x7ffff7ffada4 <time+20>:   ret 

如果不调用内核,这个函数是如何获取当前时间的呢?它的流程是:

这对 time() 的功能有意义;如果参数为 null,它只是 returns 值,但如果不是,它也将它放入参数中。我的问题是,它从哪里获得时间价值? address 0x7ffff7ff80a8 有什么神奇之处,它是如何在没有系统调用的情况下做到这一点的?

我正在使用 GCC 6.3.0 和 Ubuntu GLIBC 2.24-9ubuntu2.2。

读取time(7). Probably your call to time(2) uses the vdso(7) (maybe via clock_gettime(2) or via __vdso_time). If vdso(7)被使用,

When tracing systems calls with strace(1), symbols (system calls) that are exported by the vDSO will not appear in the trace output.

详细信息可能是特定于内核和 libc 的(当然还有特定于体系结构的)。

出于类似的 vDSO 原因,strace date 不显示任何与时间相关的系统调用。

而且 vDSO 是一个非常方便的功能(取决于 ASLR). Thanks to it, timing calls (e.g. clock_gettime(2)...) go really quick (about 40 nanoseconds on my i5-4690S). AFAIU, no context switch (or user to kernel mode 过渡)正在发生。

所以您的 0x7ffff7ff80a8 可能位于 vDSO 中(并且内核确保它包含当前时间)。您可以使用 proc(5) (e.g. reading and showing /proc/self/maps from your program), or perhaps using ldd(1) and pmap(1)

进行检查