任何人都可以理解gettimeofday是如何工作的?

ask*_*ker 8 assembly x86-64 system-calls

根据此页面,gettimeofday是一个x86-86的系统调用(只需gettimeofday在框中搜索):

int gettimeofday(struct timeval *tv, struct timezone *tz);
Run Code Online (Sandbox Code Playgroud)

我认为迪斯应该很容易,只需准备两个指针并调用相关的syscall.

但它的disas做得更多:

(gdb) disas gettimeofday
Dump of assembler code for function gettimeofday:
0x00000034f408c2d0 <gettimeofday+0>: sub    $0x8,%rsp
0x00000034f408c2d4 <gettimeofday+4>: mov    $0xffffffffff600000,%rax
0x00000034f408c2db <gettimeofday+11>: callq  *%rax
0x00000034f408c2dd <gettimeofday+13>: cmp    $0xfffff001,%eax
0x00000034f408c2e2 <gettimeofday+18>: jae    0x34f408c2e9 <gettimeofday+25>
0x00000034f408c2e4 <gettimeofday+20>: add    $0x8,%rsp
0x00000034f408c2e8 <gettimeofday+24>: retq   
0x00000034f408c2e9 <gettimeofday+25>: mov    0x2c4cb8(%rip),%rcx        # 0x34f4350fa8 <free+3356736>
0x00000034f408c2f0 <gettimeofday+32>: xor    %edx,%edx
0x00000034f408c2f2 <gettimeofday+34>: sub    %rax,%rdx
0x00000034f408c2f5 <gettimeofday+37>: mov    %edx,%fs:(%rcx)
0x00000034f408c2f8 <gettimeofday+40>: or     $0xffffffffffffffff,%rax
0x00000034f408c2fc <gettimeofday+44>: jmp    0x34f408c2e4 <gettimeofday+20>
End of assembler dump. 
Run Code Online (Sandbox Code Playgroud)

而且我根本看不到syscall.

任何人都明白它是如何工作的?

Fra*_*kH. 8

gettimeofday()在Linux上是所谓的vsyscall和/或vdso.因此,你看到两行:

0x00000034f408c2d4 : mov    $0xffffffffff600000,%rax
0x00000034f408c2db : callq  *%rax

在你的反汇编.地址0xffffffffff600000是vsyscall页面(在x86_64上).

该机制将特定的内核创建的代码页映射到用户内存中,因此可以在没有用户/内核上下文切换的开销的情况下进行一些"系统调用",而是作为"普通"函数调用.实际的实施就在这里.

  • 这就是 vsyscall 页面的重点——它是一个 _kernel-created_ 页面(因此恰好在内核 VA 范围内),在创建进程地址空间时“_exported_”(即映射)到用户空间。对于用户空间应用程序,它看起来就像另一个链接器预加载的共享对象(即使内核本身执行此“预加载”),因此是“vdso.so”。内核设置权限,以便用户空间可以读取(但不能写入)它。 (4认同)

dra*_*oot 7

Syscalls通常会产生很多开销,并且考虑到gettimeofday()调用的丰富程度,人们宁愿不使用系统调用.为此,Linux内核可以将一个或两个特殊区域映射到每个程序中,称为vdso和vsyscall.你的gettimeofday()实现似乎是使用vsyscall:

mov $0xffffffffff600000,%rax

这是vsyscall地图的标准地址.试着cat /proc/self/maps看看那个映射.vsyscall背后的想法是内核提供了一些函数的快速用户空间实现,而libc只是调用它们.

阅读这篇好文章了解更多详情.