/**
- @file runtime_checkpoints.md
- @brief 运行时状态检测(Runtime Checkpoints)
- @section checkpoint_overview 概述
- 在栈溢出检测与内存访问越界检测中,
- OpenVela 已经通过编译器插桩与运行时校验机制,
- 实现了对“明确非法行为”的即时捕获。
- 然而,在实际工程中仍然存在大量问题:
-
- 系统尚未崩溃,但内部状态已经逐步异常;
-
- 内存、链表、调度状态被破坏,但暂未触发致命错误;
-
- 问题发生频率极低,难以稳定复现;
-
- 出于性能或覆盖范围限制,部分即时检测机制未启用。
- 在这些场景下,系统仍可继续运行,
- 但其内部状态已经偏离设计预期。
- 一旦后续发生 Crash,问题演化路径往往已经不可追溯。
- 运行时状态检测(Runtime Checkpoints)
- 正是为解决这一类问题而引入的一种诊断机制。
- 与栈溢出 / 内存越界检测不同,
- Checkpoint 的核心目标并不是“立即判定错误”,
- 而是:
-
- 在系统仍可运行时,
-
- 对关键系统状态进行校验或冻结,
-
- 在问题尚未演变为崩溃之前提前暴露异常迹象。
- @section checkpoint_why 为什么需要 Checkpoint
- 大多数严重系统问题,在最终崩溃之前,
- 都会经历一个“隐患阶段”:
-
- 内存管理链表被悄然破坏;
-
- 调度器内部状态不一致;
-
- 任务状态机进入非法组合;
-
- 同步原语(锁 / 信号量)数量异常。
- 这些问题在初期往往不会立即导致系统停止,
- 系统甚至可以继续运行相当长一段时间。
- 但一旦某次 malloc / free / 调度 / 上下文切换触发临界路径,
- 就会以 HardFault、死锁或随机崩溃的形式“延迟爆发”。
- 如果仅依赖 Crash 之后的现场分析,
- 工程师面对的往往是:
-
- 被严重破坏的内存结构;
-
- 无法还原的状态演化过程;
-
- 与根因相距甚远的崩溃点。
- Checkpoint 的价值在于:
-
- 将问题从“崩溃后分析”,前移到“运行中发现”;
-
- 在系统尚未失控之前暴露异常;
-
- 为后续 Crash 分析提供关键上下文线索。
- @section checkpoint_how Checkpoint 的实现方式
- 运行时状态检测通常以 轻量级一致性校验 的形式存在,
- 并直接嵌入在系统关键路径中。
- 一个典型的 Checkpoint 示例为:
- @code
- DEBUGASSERT(node->blink->flink == node);
- @endcode
- 该检查用于验证双向链表结构的一致性:
-
- 对于任意节点 node,
-
- 其前驱节点 node->blink 的 flink
-
- 必须指回当前节点 node。
- 一旦该关系被破坏,说明:
-
- 链表结构已经发生损坏;
-
- 即便 heap 当前仍可能“看似可用”,
- 后续操作也极有可能触发严重错误。
- Checkpoint 的关键特点包括:
-
- 检查逻辑简单、直接;
-
- 不依赖复杂插桩或外部工具;
-
- 可在系统任意关键路径中按需插入;
-
- 失败时可立即触发 ASSERT / PANIC,
- 阻止错误进一步扩散。
- @section checkpoint_scope 覆盖的典型问题类型
- 运行时状态检测主要用于捕获以下问题:
-
- 内存管理结构异常
-
- 空闲链表断裂
-
- 双向链表前后指针不一致
-
- 调度与任务状态异常
-
- 任务状态非法
-
- 调度队列结构被破坏
-
- 状态机失配
-
- 非法状态跳转
-
- 状态组合不可能同时成立
-
- 同步原语异常
-
- 锁 / 信号量数量异常
-
- 资源泄漏或重复释放
- 这些问题往往:
-
- 不属于“非法内存访问”;
-
- 不一定触发栈越界;
-
- 但会在系统运行过程中逐步放大影响。
- @section checkpoint_relation 与其他运行时诊断机制的关系
- 在 OpenVela 的调试体系中:
-
- 栈溢出检测(3.1)关注:
-
栈空间是否被整体用穿;
-
- 内存访问越界检测(3.2)关注:
-
单次内存访问是否合法;
-
- 运行时状态检测(3.3)关注:
-
系统关键数据结构和状态是否仍保持一致。
- 三者并不互相替代,而是形成互补关系:
-
- 栈 / 内存检测解决“非法行为”;
-
- Checkpoint 解决“非法状态”;
-
- 共同目标是:
-
在系统彻底崩溃之前,尽可能提前发现问题。
- @section checkpoint_scene 使用建议
- 运行时状态检测适用于:
-
- 系统核心路径(调度、内存管理、IPC);
-
- 难以复现的随机性问题排查;
-
- 调试版本或稳定性验证阶段。
- 在 Release 场景下,
- 可根据性能与可靠性需求,
- 选择性保留关键 Checkpoint,
- 以在开销可控的前提下,
- 提供最后一道运行时安全防线。 */