我应该在使用 HPET 的 x86_64 上看到(非 VDSO)clock_gettime() 系统调用吗?

i33*_*36_ 2 clock

在无数次查找如何使用gettimeofday()时,我决定这次快速深入了解一下 vDSO,因为我对它只有一个模糊的认识,并且想知道是否有任何我应该注意的使用陷阱。

根据/sf/ask/2983569921/,如果 vDSO 正在使用,则strace不应显示或。gettimeofdayclock_gettime

嗯,看起来我的 ThinkPad T400 已经坏了一段时间了:从我记事起,我就一直看到“大量”这样的电话。strace(特别是来自 QEMU。)

如果我尝试testgtod.c(运行gettimeofday()1000 次)上述问题:

$ strace ./testgtod 2>&1 | grep clock_gettime | wc -l
1000
Run Code Online (Sandbox Code Playgroud)

目前,我能发现的 ThinkPad 和 i3 台式机之间的唯一区别是 i3 使用 TSC,而 ThinkPad 使用 HPET,因为tsc: Marking TSC unstable due to TSC halts in idle. (想知道这是否是一个暂停/恢复的事情,但后来注意到了时间戳 - 这是启动后的 1.53 秒。)T400(当前......)运行 Arch,而 i3 盒子运行 Debian 9。

上述问题也参考了dump-vdso.c。T400 上的 vDSO 对我来说看起来相当不错:

$ objdump -T vdso.so

vdso.so:     file format elf64-x86-64

DYNAMIC SYMBOL TABLE:
0000000000000740  w   DF .text  000000000000005e  LINUX_2.6   clock_gettime
00000000000007a0 g    DF .text  0000000000000067  LINUX_2.6   __vdso_gettimeofday
00000000000007a0  w   DF .text  0000000000000067  LINUX_2.6   gettimeofday
0000000000000810 g    DF .text  0000000000000010  LINUX_2.6   __vdso_time
0000000000000810  w   DF .text  0000000000000010  LINUX_2.6   time
0000000000000740 g    DF .text  000000000000005e  LINUX_2.6   __vdso_clock_gettime
0000000000000000 g    DO *ABS*  0000000000000000  LINUX_2.6   LINUX_2.6
0000000000000820 g    DF .text  0000000000000025  LINUX_2.6   __vdso_getcpu
0000000000000820  w   DF .text  0000000000000025  LINUX_2.6   getcpu
Run Code Online (Sandbox Code Playgroud)

我发现的另一个链接https://bert-hubert.blogspot.com/2017/03/on-linux-vdso-and-clockgettime.html表示 vDSO 代码缺乏对某些计时器的支持,并将回退到系统调用(如果您使用其中之一)。该文章来自 2017 年,https://lore.kernel.org/linux-arm-kernel/20190621095252.32307-1-vincenzo.frascino@arm.com/(2019 年 6 月)中的详细信息表明几乎所有(如果不是全部? ) 计时器现在具有 vDSO 支持,但无论如何,testgtod上面提到的程序称为CLOCK_REALTIME,2017 年的文章称该程序当时受 vDSO 支持。

所以:我很困惑:)

通过阅读http://btorpey.github.io/blog/2014/02/18/clock-sources-in-linux/,我看到很多TSC的引用。这篇文章并没有真正提到它,但我开始认为这可能RDTSC{,P}是一个可以从用户空间调用的非特权指令,而从 HPET 读取需要内核级访问(对硬件或计时器值)。这可以完全解释系统调用后备。

顺便说一句,我的 T400 中的 Core2 P8600 确实支持tscconstant_tsc,但不支持nonstop_tsc

如果有更多声誉的人想要添加其中一个或多个,则 都不存在。

Ste*_*itt 5

\n

这篇文章并没有真正提到它,但我开始认为这可能RDTSC{,P}是一个可以从用户空间调用的非特权指令,而从 HPET 读取需要内核级访问(对硬件或计时器值)。这可以完全解释系统调用后备。

\n
\n\n

这就是原因。

\n\n

tsc您可以在支持和hpet作为时间源的任何系统上验证两个时钟之间 vDSO 行为的变化:

\n\n
$ cat /sys/devices/system/clocksource/clocksource0/available_clocksource\ntsc hpet acpi_pm\n\n$ echo tsc | sudo tee /sys/devices/system/clocksource/clocksource0/current_clocksource > /dev/null\n\n$ strace -e clock_gettime date\nSun 24 Nov 10:49:49 CET 2019\n+++ exited with 0 +++\n\n$ echo hpet | sudo tee /sys/devices/system/clocksource/clocksource0/current_clocksource > /dev/null\n\n$ strace -e clock_gettime date\nclock_gettime(CLOCK_REALTIME, {tv_sec=1574589034, tv_nsec=589851883}) = 0\nSun 24 Nov 10:50:34 CET 2019\n+++ exited with 0 +++\n
Run Code Online (Sandbox Code Playgroud)\n\n

(记得恢复原来的时钟源。)

\n\n

RDTSC是一个非特权指令,你可以在GCC 手册中看到它的使用示例:在那里搜索rdtsc,编译示例代码,你\xe2\x80\x99会看到你可以在用户空间中运行它。(严格来说,RDTSC并且RDTSCP 可以被授予特权,在Linux下默认情况下它们是\xe2\x80\x99t,但是可以使用使它们获得特权prctl。)

\n\n

在vDSO中,clock_gettimeofday相关功能依赖于特定的时钟模式;看__arch_get_hw_counter。如果时钟模式为VCLOCK_TSC,则无需系统调用即可读取时间,使用RDTSC; 如果 it\xe2\x80\x99sVCLOCK_PVCLOCKVCLOCK_HVCLOCK,则 it\xe2\x80\x99s 从特定页面读取以从管理程序检索信息。HPET不\xe2\x80\x99t 声明时钟模式,因此最终采用默认模式VCLOCK_NONE,并且 vDSO 发出系统调用来检索时间。

\n\n

您链接到的补丁集不是\xe2\x80\x99,而是关于跨时钟统一时钟处理,而是跨架构统一它。还有一些时钟不支持 vDSO,其中包括 HPET 和 ACPI。

\n