RFC-0074:公开进程开始时间

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(符合当前系统调用结构体政策),保存一个字节 而且不会增加执行此方法所需的工作量 提案(这样也能避免下一位工程师的麻烦)。

实现

  1. 将旧结构体重命名为 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)。

  2. 添加新结构体 (zx_info_process_v2_t) 和主题 (ZX_INFO_PROCESS_V2)。更改内核以跟踪进程启动时间和 识别新的主题和结构。

  3. 更新所有代码(树内和树外)以使用 ZX_INFO_PROCESS_V2

  4. ZX_INFO_PROCESSzx_info_process_t 别名更改为引用 v2 主题和结构。

  5. 请等待先前的更改完全发布。

  6. 更新所有代码(树内和树外)以再次使用 ZX_INFO_PROCESS

  7. 移除 v1 主题和结构体以及 v2 别名。

这些类型的 Rust 和 Go 版本将进行类似更新。

性能

添加的逻辑会产生可以忽略不计的运行时成本,特别是 在单个进程的生命周期内摊销。

安全注意事项

如果程序已经拥有进程的句柄,它就可以做和收集更多 该进程的开始时间。此外,开始时间已设为 出现在一些其他操作系统中,而这似乎并没有什么顾虑。

隐私注意事项

请参阅上文中的安全注意事项

测试

Zircon 的与流程相关的核心测试将扩展,以声明 在 zx_process_start() 之前和之后获取的时间样本的确会 以及尚未开始的进程 ZX_INFO_PROCESS_FLAG_STARTED未设置。

文档

ZX_INFO_PROCESS 文档将进行相应更新。

缺点、替代方案和未知问题

此外,我们还考虑了公开“start”比较笼统地介绍 概念(例如在 ZX_INFO_TASK_RUNTIME 下提供)。对于线程, 以缩进方式扩展:线程的开始时间是 调用 zx_thread_start()。对工作而言,最自然的表述是 “启动”当其第一个子级启动时。由于作业可以嵌套 不过,这会引入遍历任务子树, 这比处理另外两种任务类型要复杂。归根结底, 拒绝了这些扩展程序,因为它们无法满足当前的需求, 这样我们就可以回避对任务层次结构遍历的需求。

先验技术和参考资料

Linux:/proc/[pid]/stat 公开了 starttime。 FreeBSD:/proc/[pid]/status 在以空格分隔的统计信息列表中公开开始时间。 macOS:proc_pidinfo() 系统调用似乎公开了此问题。