为什么time.h中的time()没有syscall到sys_time?

Leo*_*all 9 linux assembly gcc glibc x86-64

我写了一个非常简单的程序,调用time()说明使用strace,但我遇到了问题; 这个time()电话似乎并没有真正产生一个系统调用!

我最终进入了time()GDB 的功能,现在我比以前更加困惑.从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 
Run Code Online (Sandbox Code Playgroud)

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

  • 序幕
  • (0x7ffff7ffad94 + 0xffffffffffffd30d)(0x7ffff7ff80a8)中获取一些值并将其放入rax(将被返回)
  • 检查rdi(第一个参数)是否为null
  • 如果没有将值放在rax(返回值)中那么
  • 结语

这对于功能而言是有意义的time(); 如果参数为null,它只返回值,但如果不是,它也将它放在参数中.我的问题是,它在哪里得到时间价值?什么是如此神奇的地址0x7ffff7ff80a8,如何在没有系统调用的情况下做到这一点?

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

Bas*_*tch 6

阅读时间(7).可能你对时间(2)的调用使用vdso(7)(可能通过clock_gettime(2)或via __vdso_time).如果使用vdso(7),

使用strace(1)跟踪系统调用时,vDSO导出的符号(系统调用)不会出现在跟踪输出中.

细节可以是内核和libc特定的(当然还有特定于体系结构).

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

vDSO是一个非常方便的功能.多亏了它,定时调用(例如clock_gettime(2) ......)非常快(我的i5-4690S大约需要40纳秒).AFAIU,没有上下文切换(或用户到内核模式转换)正在发生.

所以你0x7ffff7ff80a8可能坐在vDSO中(内核确保它包含当前时间).您可以使用proc(5)进行检查(例如,从程序中读取和显示/proc/self/maps),或者使用ldd(1).