为什么timetime中的time()没有系统调用sys_time? [英] Why doesn't time() from time.h have a syscall to sys_time?
问题描述
我写了一个非常简单的程序来调用 time()
来说明 strace
的用法,有问题的; time()
调用似乎实际上并没有产生系统调用!
我最终进入了 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
如果该函数不调用内核,该函数如何实际获取当前时间?它的流程是:
$ b
- 序言
- 从
获取一些值(0x7ffff7ffad94 + 0xffffffffffffd30d)
(0x7ffff7ff80a8
)并将其放入rax中(将返回)
- 检查rdi (第一个参数)为空
- 如果不是将值放入rax(返回值),那么还有
- 结尾
这对于
time()
的功能是有意义的。如果参数为空,它只是返回值,但如果不是,它也将它放入参数中。我的问题是,它在哪里获得时间价值?有什么神奇的地址0x7ffff7ff80a8
,它是如何在没有系统调用的情况下做到这一点的?
我使用GCC
阅读时间(7)。可能您致电时间(2)时会使用 vdso(7)(也许通过 clock_gettime(2)或通过__ vdso_time
)。如果使用 vdso(7),则
当使用 strace(1),由vDSO导出的符号(系统调用)
将 not 出现在跟踪输出中。
详细信息可以是kernel和libc的具体信息(当然也可以是架构特定的)。
a href =https://en.wikipedia.org/wiki/VDSO =noreferrer> vDSO 原因,
strace date
不显示任何时间相关的系统调用。
vDSO是一个非常方便的功能。感谢它,定时调用(例如 clock_gettime(2)。 ..)非常快(我的i5-4690S大约40纳秒)。 AFAIU,没有上下文切换(或用户转到内核
因此,您的
code>可能位于vDSO中(并且内核确保它包含当前时间)。您可以使用 proc(5)进行检查(例如阅读并在程序中显示0x7ffff7ff80a8
/ proc / self / maps
),或者也许使用 ldd(1)。I wrote a very simple program with calls
time()
to illustrate the use ofstrace
, but I'm having a problem; thetime()
call doesn't seem to actually produce a syscall!I ended up stepping into the
time()
function in GDB and now I'm more confused than ever. From the disassembly of thetime()
function: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
How is this function actually getting the current time if it does not call the kernel? Its flow is:
- Prologue
- Get some value from
(0x7ffff7ffad94 + 0xffffffffffffd30d)
(0x7ffff7ff80a8
) and put it in rax (to be returned) - Check if rdi (first argument) was null
- If not put the value in rax (return value) there also
- Epilogue
This makes sense with the functionality of
time()
; if the argument is null, it just returns the value, but if not it also puts it in the argument. The question I have is, where is it getting the time value? What's so magical about address0x7ffff7ff80a8
, and how does it do this without a syscall?I'm using GCC 6.3.0 and Ubuntu GLIBC 2.24-9ubuntu2.2.
解决方案Read time(7). Probably your call to time(2) uses the vdso(7) (maybe via clock_gettime(2) or via
__vdso_time
). If vdso(7) is used,When tracing systems calls with strace(1), symbols (system calls) that are exported by the vDSO will not appear in the trace output.
Details could be kernel and libc specific (and of course architecture specific).
For similar vDSO reasons,
strace date
don't show any time-related syscalls.And vDSO is a really handy feature. 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 transition) is happening.
So your
0x7ffff7ff80a8
is probably sitting in the vDSO (and the kernel ensures it contains the current time). You might check by using proc(5) (e.g. reading and showing/proc/self/maps
from your program), or perhaps using ldd(1).这篇关于为什么timetime中的time()没有系统调用sys_time?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!