POSIX 時間 API

最後更新: 2023-08-09 17:37:46 +0800 +0800
tags: Linux | Posix | Time
原文以英文撰寫。您正在閱讀AI翻譯版本。

時間 API 回答不同問題:民用時間為某個瞬間命名,單調時間測量一段間隔,而 CPU 時鐘測量工作消耗的執行時間。選錯時鐘會讓逾時回應掛鐘修正,或讓 I/O 等待從測量中消失。

時鐘選擇 #

clock_gettime 將 clockid_t 讀入 struct timespec,其 tv_sec 與 tv_nsec 欄位表示秒與奈秒。POSIX 要求 CLOCK_REALTIME(從 Epoch 起算的系統民用時鐘)與 CLOCK_MONOTONIC(起點未指定且不可設定)。時間戳記使用即時時鐘,經過時間與期限則使用單調時鐘。

在支援時,CLOCK_PROCESS_CPUTIME_ID 與 CLOCK_THREAD_CPUTIME_ID 會測量程序或單一執行緒消耗的 CPU 執行時間。它們不包含 I/O 阻塞或取消排程的時間。Linux 也提供包含暫停時間的 CLOCK_BOOTTIME;它是 Linux 擴充功能,不是可攜式 POSIX 選擇。

c
struct timespec start, end;
clock_gettime(CLOCK_MONOTONIC, &start);
/* operation */
clock_gettime(CLOCK_MONOTONIC, &end);

clock_getres 回報實作的解析度,而不是保證連續讀取會不同。排程延遲、計時器合併與硬體都會影響程式碼執行時間。當某個瞬間無法放入 time_t 時,呼叫可能以 EOVERFLOW 失敗;請驗證 tv_nsec、處理跨秒邊界的算術,且不要假設 time_t 具有固定寬度。

睡眠與計時器 #

nanosleep 提供相對延遲。訊號可能以 EINTR 中斷它並回報剩餘時間,但在週期性程式碼中從剩餘時間重新啟動仍會累積工作與排程延遲。每個週期計算一個單調時鐘的絕對期限,並使用 clock_nanosleep(CLOCK_MONOTONIC, TIMER_ABSTIME, ...) 等待;已過期的期限會立即返回,因此呼叫端必須選擇略過工作或追趕進度。

POSIX 計時器使用 timer_create 與 timer_settime;TIMER_ABSTIME 使要求的到期時間成為所選時鐘上的絕對時間。通知可以是訊號或執行緒通知,各自有不同的排隊與生命週期含義。Linux 的 timerfd_create 不是 POSIX,但能將計時器到期整合至 poll、select 與 epoll。alarm 與 setitimer 是以訊號為導向的舊式介面。

相對等待不受後續 CLOCK_REALTIME 調整影響,而絕對即時期限會隨該時鐘移動。因此,除非產品需求明確要求「在這個民用時間瞬間」,否則請在單調時鐘上表示逾時期限。

民用時間與時區 #

time_t 是純量時間值;struct tm 是拆解後的曆法時間。gmtime_r 轉換為 UTC,而 localtime_r 使用程序時區規則進行轉換。其非 _r 對應版本使用可重複使用的靜態儲存空間。mktime 將 struct tm 解讀為本地民用時間;將 tm_isdst 設為 -1 可讓它判斷日光節約時間狀態。timegm 是解讀拆解 UTC 的實用 GNU 擴充功能,不是 POSIX 介面。

TZ 與 tzset 控制程序的時區狀態。秋季日光節約時間轉換中的本地時間可能指向兩個瞬間;春季跳過的本地時間可能一個瞬間也不指向。請以 UTC 或 time_t 儲存瞬間,若面向使用者的值必須保留其民用時間意義,則攜帶明確時區或偏移量。

POSIX 時間不會將閏秒建模為獨立的純量時間秒。同步時系統可能調整或平滑即時時鐘;因此,time_t 算術或單獨的 UTC 轉換 API 都不是完整的閏秒表示方式。

POSIX clock 規格 與 clock_nanosleep(3) 定義可攜式及 Linux 特定細節。

評論

在 GitHub 上閱讀或評論(發表評論需要登入)