RFC-0074:公開程序開始時間 | |
---|---|
狀態 | 已接受 |
區域 |
|
說明 | 讓從使用者空間查詢的程序啟動時間。 |
Gerrit 變更 | |
作者 | |
審查人員 | |
提交日期 (年-月-日) | 2021-02-19 |
審查日期 (年-月-日) | 2021-03-11 |
摘要
我們會重構 ZX_INFO_PROCESS
,以便公開程序的開始時間,並清理描述其執行時間的標記。當 ZX_INFO_PROCESS_FLAG_STARTED
標記出現時,我們會說程序具有有效的開始時間,並將其定義為呼叫 zx_process_start()
時的單調時間 (如果有效的話)。
提振精神
這個問題最初是在 crbug.com/726484 和 https://fxbug.dev/42105649 中提出,Chromium 要求提供這項功能,以便為追蹤事件提供基本時間,並擴充已支援 Linux、macOS 和 Windows 的平台無關介面。此外,https://fxbug.dev/42119376 已提出申請,以便利用這項功能,在當機報告中加入正常運作時間。
設計
在 ProcessDispatcher
的小型簡單擴充功能中,我們會在 ProcessDispatcher::AddInitializedThread()
中為初始執行緒記錄時間,然後在 ProcessDispatcher::GetInfo()
中傳遞該時間;前者是 zx_process_start()
的主要「啟動」例行程序,而後者是 zx_get_object_info()
的例行程序,用於處理具有 ZX_INFO_PROCESS
的程序句柄。
就 zx_object_get_info()
填入的結構體而言,目前我們有:
typedef struct zx_info_process {
// The process's return code; only valid if |exited| is true.
// If the process was killed, it will be one of the ZX_TASK_RETCODE values.
int64_t return_code;
// True if the process has ever left the initial creation state,
// even if it has exited as well.
bool started;
// If true, the process has exited and |return_code| is valid.
bool exited;
// True if a debugger is attached to the process.
bool debugger_attached;
uint8_t padding1[5];
} zx_info_process_t;
我們會將其改良為:
typedef struct zx_info_process {
// The process's return code; only valid if the
// |ZX_PROCESS_INFO_FLAG_EXITED| flag is set. If the process was killed, it
// will be one of the |ZX_TASK_RETCODE| values.
int64_t return_code;
// The monotonic time at which zx_process_start() was called, only valid
// if the |ZX_INFO_PROCESS_FLAG_STARTED| flag is set.
zx_time_t start_time;
// Bitwise OR of ZX_INFO_PROCESS_FLAG_* values.
uint32_t flags;
uint8_t padding1[4];
} zx_info_process_t;
並引入下列標記值:
// Whether the process has started. zx_process_info_t::start_time is only
// valid if this flag is set.
#define ZX_INFO_PROCESS_FLAG_STARTED (1u << 0)
// Whether the process has exited.
#define ZX_INFO_PROCESS_FLAG_EXITED (1u << 1)
// Whether a debugger is attached to the process.
#define ZX_INFO_PROCESS_FLAG_DEBUGGER_ATTACHED (1u << 2)
布林值至旗標的重構並非必要,但這麼做可讓 zx_info_process_t
符合目前的系統呼叫結構體政策,節省填充的位元組,且不會增加執行此提案所需的工作量 (也能讓下一位工程師免於相當麻煩的情況)。
實作
將舊結構體重新命名為
zx_info_process_v1_t
,並建立別名以便以舊名稱 (zx_info_process_t
->zx_info_process_v1_t
) 參照該結構體。將主題ZX_INFO_PROCESS
重新命名為ZX_INFO_PROCESS_V1
,並建立別名以便以舊名稱 (ZX_INFO_PROCESS
->ZX_INFO_PROCESS_V1
) 參照該主題。新增結構體 (
zx_info_process_v2_t
) 和主題 (ZX_INFO_PROCESS_V2
)。變更核心,以便追蹤程序開始時間,並辨識新主題和結構體。更新所有程式碼 (樹狀結構內和樹狀結構外),以便使用
ZX_INFO_PROCESS_V2
。變更
ZX_INFO_PROCESS
和zx_info_process_t
別名,以便參照 v2 主題和結構體。等待先前變更全面推出。
更新所有程式碼 (樹狀結構內和樹狀結構外),再次使用
ZX_INFO_PROCESS
。移除 v1 主題和結構體,以及 v2 別名。
這些類型的 Rust 和 Go 版本也會以類似方式更新。
成效
新增的邏輯應會產生微不足道的執行階段成本,尤其是在個別程序的整個生命週期中,這項成本會攤銷。
安全性考量
如果程式已擁有程序的句柄,則可執行及擷取比該程序啟動時間更詳細的資訊。此外,在許多其他作業系統中,開始時間已公開揭露,但似乎沒有人擔心。
隱私權注意事項
請參閱上方的安全性考量。
測試
Zircon 的程序相關核心測試將擴充,以便宣告 zx_process_start()
前後擷取的時間樣本確實夾在已記錄的開始時間之間,以及尚未開始的程序已取消設定 ZX_INFO_PROCESS_FLAG_STARTED
。
說明文件
ZX_INFO_PROCESS
說明文件也將隨之更新。
缺點、替代方案和未知事項
我們也考慮將「開始」時間公開為更一般性的任務層級概念 (例如在 ZX_INFO_TASK_RUNTIME
下公開)。對於執行緒,情況則是相同的:執行緒的開始時間是呼叫 zx_thread_start()
的時間點。對於工作而言,最自然的說法是,當第一個子項開始時,工作就會「開始」。不過,由於工作可以巢狀,這會引入檢查工作子樹狀結構,而這比處理其他兩種工作類型的邏輯更為複雜。最終我們決定不採用擴充功能,因為這無法滿足目前的需求,而且我們可以避免需要檢查工作群組階層。
既有技術與參考資料
Linux:/proc/[pid]/stat
會公開 starttime
。FreeBSD:/proc/[pid]/status
會在以空格分隔的統計資料清單中公開開始時間。
macOS:proc_pidinfo()
系統呼叫似乎會公開這項資訊。