| RFC-0074:公開程序啟動時間 | |
|---|---|
| 狀態 | 已接受 |
| 區域 |
|
| 說明 | 讓使用者空間可查詢程序啟動時間。 |
| Gerrit 變更 | |
| 作者 | |
| 審查人員 | |
| 提交日期 (年-月-日) | 2021-02-19 |
| 審查日期 (年-月-日) | 2021-03-11 |
摘要
我們重構 ZX_INFO_PROCESS,以公開程序的開始時間,並清除描述其執行階段的標記。如果程序有 ZX_INFO_PROCESS_FLAG_STARTED 旗標,且定義為呼叫 zx_process_start() 時的單調時間 (如果有效),則表示程序具有有效的開始時間。
提振精神
Chromium 先是在 crbug.com/726484 提出要求,然後在 https://fxbug.dev/42105649 提出要求,希望提供追蹤事件的基本時間,以擴充已支援 Linux、macOS 和 Windows 的平台無關介面。此外,https://fxbug.dev/42119376 已歸檔,目的是利用這項相同功能,在當機報告中加入正常運作時間。
設計
在 ProcessDispatcher 的小型直接擴充功能中,我們會記錄初始執行緒的 ProcessDispatcher::AddInitializedThread() 時間,然後在 ProcessDispatcher::GetInfo() 中傳遞該時間;前一個方法是 zx_process_start() 的主要「啟動」常式,後一個方法則是 ZX_INFO_PROCESS 的程序控制代碼。zx_get_object_info()
至於由 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() 系統呼叫似乎會公開這項資訊。