我應該使用 HPET 在 x86_64 上看到(非 VDSO)clock_gettime() 系統呼叫嗎?
在無數次查找如何使用
gettimeofday()
時,我決定這次快速了解 vDSO,因為我對它只有模糊的認識,並想知道是否有任何我應該注意的使用陷阱。根據https://stackoverflow.com/questions/42622427/gettimeofday-not-using-vdso ,如果vDSO正在使用中,
strace
則不應顯示or 。gettimeofday``clock_gettime
好吧,看起來我的 ThinkPad T400 已經壞了一段時間了:從我記事起,我就一直看到噸的這些電話
strace
。(特別是來自 QEMU。)如果我從上述問題嘗試
testgtod.c
(執行1000 次):gettimeofday()
$ strace ./testgtod 2>&1 | grep clock_gettime | wc -l 1000
目前,我能在 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
我發現的另一個連結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 確實支持
tsc
andconstant_tsc
,但不支持nonstop_tsc
。tsc gettimeofday clock-gettime vdso hpet 都不存在,如果有更多聲譽的人想要添加其中的一個或多個。
這篇文章並沒有真正提到它,但我開始認為這可能
RDTSC{,P}
是一個可以從使用者空間呼叫的非特權指令,而從 HPET 讀取需要核心級訪問(對硬體或計時器值)。這將完全解釋系統呼叫回退。這就是原因。
您可以在任何同時支持
tsc
和hpet
作為時間源的系統上驗證兩個時鐘之間的 vDSO 行為變化:$ cat /sys/devices/system/clocksource/clocksource0/available_clocksource tsc hpet acpi_pm $ echo tsc | sudo tee /sys/devices/system/clocksource/clocksource0/current_clocksource > /dev/null $ strace -e clock_gettime date Sun 24 Nov 10:49:49 CET 2019 +++ exited with 0 +++ $ echo hpet | sudo tee /sys/devices/system/clocksource/clocksource0/current_clocksource > /dev/null $ strace -e clock_gettime date clock_gettime(CLOCK_REALTIME, {tv_sec=1574589034, tv_nsec=589851883}) = 0 Sun 24 Nov 10:50:34 CET 2019 +++ exited with 0 +++
(記得恢復原來的時鐘源。)
RDTSC
是一個非特權指令,你可以在GCC 手冊中看到它的使用範例:在那裡搜尋rdtsc
,編譯範常式式碼,你會看到你可以在使用者空間中執行它。(嚴格來說,RDTSC
並且RDTSCP
可以是 privileged,它們在 Linux 下不是預設的,但可以使用 來獲得特權prctl
。)在 vDSO 中,
clock_gettimeofday
相關功能依賴於特定的時鐘模式;見__arch_get_hw_counter
。如果時鐘模式為VCLOCK_TSC
,則無需系統呼叫即可讀取時間,使用RDTSC
; 如果是VCLOCK_PVCLOCK
或VCLOCK_HVCLOCK
,則從特定頁面讀取以從管理程序中檢索資訊。HPET沒有聲明時鐘模式,因此它以預設值結束VCLOCK_NONE
,並且 vDSO 發出系統呼叫來檢索時間。您連結到的更新檔集不是關於跨時鐘統一時鐘處理,而是跨架構統一它。還有一些時鐘不支持 vDSO,其中包括 HPET 和 ACPI。