ktime 訪問器

裝置驅動程式可以使用 ktime_get() 和 linux/timekeeping.h 中宣告的許多相關函式來讀取當前時間。通常情況下,如果兩個訪問器都適用於特定用例,則首選名稱較短的訪問器。

基於 ktime_t 的基本介面

推薦的最簡單形式返回一個不透明的 ktime_t,其變體返回不同時鐘參考的時間

ktime_t ktime_get(void)

CLOCK_MONOTONIC

適用於可靠的時間戳和精確測量短時間間隔。在系統啟動時開始,但在掛起期間停止。

ktime_t ktime_get_boottime(void)

CLOCK_BOOTTIME

ktime_get() 類似,但在掛起時不會停止。例如,這可用於需要與其他機器在掛起操作期間同步的金鑰過期時間。

ktime_t ktime_get_real(void)

CLOCK_REALTIME

返回自 1970 年 UNIX 紀元以來使用協調世界時 (UTC) 的時間,與使用者空間的 gettimeofday() 相同。這用於所有需要在重啟後持久存在的時間戳,如 inode 時間,但應避免內部使用,因為它可能因閏秒更新、NTP 調整或使用者空間的 settimeofday() 操作而向後跳變。

ktime_t ktime_get_clocktai(void)

CLOCK_TAI

ktime_get_real() 類似,但使用國際原子時 (TAI) 參考而不是 UTC,以避免閏秒更新時的跳變。這在核心中很少有用。

ktime_t ktime_get_raw(void)

CLOCK_MONOTONIC_RAW

ktime_get() 類似,但以與硬體時鐘源相同的速率執行,不受(NTP)時鐘漂移調整的影響。這在核心中也很少需要。

納秒、timespec64 和秒輸出

對於以上所有函式,都有返回不同時間格式的變體,具體取決於使用者的要求

u64 ktime_get_ns(void)
u64 ktime_get_boottime_ns(void)
u64 ktime_get_real_ns(void)
u64 ktime_get_clocktai_ns(void)
u64 ktime_get_raw_ns(void)

與普通的 ktime_get 函式相同,但返回各自時間參考中的 u64 納秒數,這對於某些呼叫者可能更方便。

void ktime_get_ts64(struct timespec64*)
void ktime_get_boottime_ts64(struct timespec64*)
void ktime_get_real_ts64(struct timespec64*)
void ktime_get_clocktai_ts64(struct timespec64*)
void ktime_get_raw_ts64(struct timespec64*)

同上,但將時間返回為“struct timespec64”格式,分為秒和納秒。當列印時間或將其傳遞給需要“timespec”或“timeval”結構的外部介面時,這可以避免額外的除法運算。

time64_t ktime_get_seconds(void)
time64_t ktime_get_boottime_seconds(void)
time64_t ktime_get_real_seconds(void)
time64_t ktime_get_clocktai_seconds(void)
time64_t ktime_get_raw_seconds(void)

將時間返回為粗粒度版本的標量 time64_t。這避免了訪問時鐘硬體,並將秒數向下舍入到上次計時器滴答的完整秒數,使用相應的參考。

粗粒度和 fast_ns 訪問

存在一些額外的變體,適用於更專業的用例

ktime_t ktime_get_coarse(void)
ktime_t ktime_get_coarse_boottime(void)
ktime_t ktime_get_coarse_real(void)
ktime_t ktime_get_coarse_clocktai(void)
u64 ktime_get_coarse_ns(void)
u64 ktime_get_coarse_boottime_ns(void)
u64 ktime_get_coarse_real_ns(void)
u64 ktime_get_coarse_clocktai_ns(void)
void ktime_get_coarse_ts64(struct timespec64*)
void ktime_get_coarse_boottime_ts64(struct timespec64*)
void ktime_get_coarse_real_ts64(struct timespec64*)
void ktime_get_coarse_clocktai_ts64(struct timespec64*)

這些比非粗粒度版本更快,但精度較低,對應於使用者空間的 CLOCK_MONOTONIC_COARSE 和 CLOCK_REALTIME_COARSE,以及使用者空間中不可用的等效 boottime/tai/raw 時間基準。

這裡返回的時間對應於上一個計時器滴答,可能最長達 10 毫秒(對於 CONFIG_HZ=100),與讀取 'jiffies' 變數相同。只有在快速路徑中呼叫並且仍然期望優於秒級的精度,但又不能輕易使用 'jiffies' 時(例如對於 inode 時間戳),它們才有用。跳過硬體時鐘訪問可以在大多數具有可靠週期計數器的現代機器上節省大約 100 個 CPU 週期,但在帶有外部時鐘源的舊硬體上可能節省多達幾微秒。

u64 ktime_get_mono_fast_ns(void)
u64 ktime_get_raw_fast_ns(void)
u64 ktime_get_boot_fast_ns(void)
u64 ktime_get_tai_fast_ns(void)
u64 ktime_get_real_fast_ns(void)

這些變體可以在任何上下文中安全呼叫,包括在時間保持器更新期間來自不可遮蔽中斷 (NMI) 以及時鐘源斷電時進入掛起狀態。這在某些跟蹤或除錯程式碼以及機器檢查報告中很有用,但大多數驅動程式不應呼叫它們,因為在某些條件下時間可能會跳變。

已棄用的時間介面

較舊的核心使用一些其他介面,這些介面現在正在逐步淘汰,但可能會出現在此處移植的第三方驅動程式中。特別是,所有返回 'struct timeval' 或 'struct timespec' 的介面都已被替換,因為在 32 位架構上,tv_sec 成員在 2038 年會溢位。這些是推薦的替代方案

void ktime_get_ts(struct timespec*)

請改用 ktime_get()ktime_get_ts64()

void do_gettimeofday(struct timeval*)
void getnstimeofday(struct timespec*)
void getnstimeofday64(struct timespec64*)
void ktime_get_real_ts(struct timespec*)

ktime_get_real_ts64() 是直接替代,但請考慮使用單調時間(ktime_get_ts64())和/或基於 ktime_t 的介面(ktime_get()/ktime_get_real())。

struct timespec current_kernel_time(void)
struct timespec64 current_kernel_time64(void)
struct timespec get_monotonic_coarse(void)
struct timespec64 get_monotonic_coarse64(void)

這些被 ktime_get_coarse_real_ts64()ktime_get_coarse_ts64() 替代。然而,許多需要粗粒度時間的程式碼可以使用簡單的 'jiffies',而有些驅動程式可能實際上需要當今更高解析度的訪問器。

struct timespec getrawmonotonic(void)
struct timespec64 getrawmonotonic64(void)
struct timespec timekeeping_clocktai(void)
struct timespec64 timekeeping_clocktai64(void)
struct timespec get_monotonic_boottime(void)
struct timespec64 get_monotonic_boottime64(void)

這些被 ktime_get_raw()/ktime_get_raw_ts64()ktime_get_clocktai()/ktime_get_clocktai_ts64() 以及 ktime_get_boottime()/ktime_get_boottime_ts64() 替代。然而,如果特定的時鐘源選擇對使用者不重要,請考慮為了保持一致性而轉換為 ktime_get()/ktime_get_ts64()