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

时间:2018-01-14 17:57:37

标签: linux gcc assembly x86-64 glibc

我写了一个非常简单的程序,调用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 

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

  • 序言
  • (0x7ffff7ffad94 + 0xffffffffffffd30d)0x7ffff7ff80a8)获取一些价值并将其放入rax(将被退回)
  • 检查rdi(第一个参数)是否为空
  • 如果没有将值放在rax(返回值)中,那么
  • 后记

这对time()的功能有意义;如果参数为null,它只返回值,但如果不是,它也将它放在参数中。我的问题是,它在哪里得到时间价值?地址0x7ffff7ff80a8有什么神奇之处,没有系统调用怎么办呢?

我使用的是GCC 6.3.0和Ubuntu GLIBC 2.24-9ubuntu2.2。

1 个答案:

答案 0 :(得分:6)

阅读time(7)。您拨打time(2)的电话可能会使用vdso(7)(可能是clock_gettime(2)__vdso_time)。如果使用vdso(7)

  

使用strace(1)跟踪系统调用时,符号(系统调用)          由vDSO导出的 not 将出现在跟踪输出中。

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

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

vDSO是一个非常方便的功能。多亏了它,时间调用(例如clock_gettime(2) ...)非常快(我的i5-4690S大约40纳秒)。 AFAIU,没有context switch(或内核mode过渡的用户)正在发生。

所以你的0x7ffff7ff80a8可能位于vDSO中(内核确保它包含当前时间)。您可以使用proc(5)进行检查(例如reading并在您的计划中显示/proc/self/maps),或者使用ldd(1)