为什么timetime中的time()没有系统调用sys_time? [英] Why doesn't time() from time.h have a syscall to sys_time?

查看:224
本文介绍了为什么timetime中的time()没有系统调用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,没有上下文切换(或用户转到内核

    因此,您的 0x7ffff7ff80a8

    code>可能位于vDSO中(并且内核确保它包含当前时间)。您可以使用 proc(5)进行检查(例如阅读并在程序中显示 / 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; the time() 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 the time() 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 address 0x7ffff7ff80a8, 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屋!

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