gettimeofday 系统调用如何工作?
gettimeofday
是一个 x86-86 的系统调用,根据此页面 (只需在框中搜索gettimeofday
):
int gettimeofday(struct timeval *tv, struct timezone *tz);
我认为反汇编应该很容易,只需准备两个指针并调用相关的syscall
,但它的反汇编要做的事情更多:
(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.
我根本没有看到syscall
。
谁能解释它是如何工作的?
gettimeofday
is a syscall of x86-86 according to this page(just search gettimeofday
in the box):
int gettimeofday(struct timeval *tv, struct timezone *tz);
I thought the disassembly should be easy enough, just prepare the two pointers and call the related syscall
, but its disassembly is doing much more:
(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.
And I don't see syscall
at all.
Can anyone explain how it works?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
Linux 上的
gettimeofday()
称为vsyscall
和/或vdso
。因此,您会看到两行:在反汇编中。地址
0xffffffffff600000
是vsyscall页面(在x86_64上)。该机制将特定的内核创建的代码页映射到用户内存中,以便可以在没有用户/内核上下文切换开销的情况下进行一些“系统调用”,而是作为“普通”函数调用。实际的实现是就在这里。
gettimeofday()
on Linux is what's called avsyscall
and/orvdso
. Hence you see the two lines:in your disassembly. The address
0xffffffffff600000
is the vsyscall page (on x86_64).The mechanism maps a specific kernel-created code page into user memory, so that a few "syscalls" can be made without the overhead of a user/kernel context switch, but rather as "ordinary" function call. The actual implementation is right here.
系统调用通常会产生大量开销,并且考虑到大量的 gettimeofday() 调用,人们宁愿不使用系统调用。为此,Linux 内核可能会将一两个特殊区域映射到每个程序中,称为 vdso 和 vsyscall。您的 gettimeofday() 实现似乎正在使用 vsyscall:
mov $0xffffffffff600000,%rax
这是 vsyscall 映射的标准地址。尝试 cat /proc/self/maps 来查看该映射。 vsyscall 背后的想法是内核提供某些函数的快速用户空间实现,而 libc 只是调用它们。
阅读这篇好文章了解更多详细信息。
Syscalls generally create a lot of overhead, and given the abundance of gettimeofday() calls, one would prefer not to use a syscall. To that end, Linux kernel may map one or two special areas into each program, called vdso and vsyscall. Your implementation of gettimeofday() seems to be using vsyscall:
mov $0xffffffffff600000,%rax
This is the standard address of vsyscall map. Try
cat /proc/self/maps
to see that mapping. The idea behind vsyscall is that kernel provides fast user-space implementations of some functions, and libc just calls them.Read this nice article for more details.