Кто-нибудь может понять, как работает gettimeofday? - PullRequest
8 голосов
/ 01 сентября 2011

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.

Кто-нибудь понимает, как это работает?

Ответы [ 2 ]

8 голосов
/ 01 сентября 2011

gettimeofday() в Linux - это то, что называется vsyscall и / или vdso. Следовательно, вы видите две строки:

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

в вашей разборке. Адрес 0xffffffffff600000 является страницей vsyscall (на x86_64).

Механизм отображает определенную кодовую страницу, созданную ядром, в пользовательскую память, так что несколько «системных вызовов» могут быть выполнены без дополнительных затрат на переключение контекста пользователя / ядра, а скорее как «обычный» вызов функции. Фактическая реализация прямо здесь .

7 голосов
/ 01 сентября 2011

Системные вызовы обычно создают много накладных расходов, и, учитывая обилие вызовов gettimeofday (), кто-то предпочел бы не использовать системный вызов.Для этого ядро ​​Linux может отображать одну или две специальные области в каждую программу, называемые vdso и vsyscall.Ваша реализация gettimeofday (), похоже, использует vsyscall:

mov $0xffffffffff600000,%rax

Это стандартный адрес карты vsyscall.Попробуйте cat /proc/self/maps, чтобы увидеть это отображение.Идея, лежащая в основе vsyscall, заключается в том, что ядро ​​обеспечивает быструю реализацию некоторых функций в пользовательском пространстве, а libc просто вызывает их.

Прочитайте эту хорошую статью для получения более подробной информации.

...