土法炼钢兴趣小组的算法知识备份

【操作系统百科】内核并发的形式化验证

文章导航

分类入口
os
标签入口
#formal-verification#herd7#litmus-test#cbmc#tla-plus

目录

并发 bug 难以复现、难以调试。lockdep 和 KCSAN 能抓一部分,但形式化验证可以穷举所有可能的执行序列。

一、先看图

flowchart TD
    CODE[内核并发代码] --> LITMUS[Litmus Test<br/>小片段建模]
    CODE --> CBMC_M[CBMC<br/>C 代码有界验证]
    CODE --> TLA[TLA+<br/>协议级建模]

    LITMUS --> HERD[herd7 + LKMM<br/>穷举内存序]
    CBMC_M --> SAT[SAT/SMT 求解器]
    TLA --> TLC[TLC 模型检查器]

    HERD --> BUG[发现违反?]
    SAT --> BUG
    TLC --> BUG

    classDef tool fill:#388bfd22,stroke:#388bfd,color:#adbac7;
    classDef result fill:#f0883e22,stroke:#f0883e,color:#adbac7;
    class LITMUS,CBMC_M,TLA tool
    class HERD,SAT,TLC tool
    class BUG result

二、herd7 与 Litmus Test

2.1 什么是 litmus test

一个最小化的并发场景——几行代码、两三个线程、一个待验证的断言。

C MP+wmb+rmb
{
    int x = 0; int y = 0;
}

P0(int *x, int *y) {
    WRITE_ONCE(*x, 1);
    smp_wmb();
    WRITE_ONCE(*y, 1);
}

P1(int *x, int *y) {
    int r0 = READ_ONCE(*y);
    smp_rmb();
    int r1 = READ_ONCE(*x);
}

exists (1:r0=1 /\ 1:r1=0)

2.2 运行

herd7 -conf linux-kernel.cfg MP+wmb+rmb.litmus
# 结果:Never(不可能出现)或 Sometimes(可能出现)

herd7 穷举 LKMM 允许的所有执行序列。

2.3 内核中的 litmus tests

ls tools/memory-model/litmus-tests/
# 几十个标准 litmus tests

三、CBMC

3.1 什么是 CBMC

C Bounded Model Checker:对 C 代码做有界模型检查。

给定循环上界 → 展开所有路径 → 转化为 SAT 问题 → 求解器判断 assert 是否可能违反。

3.2 用法

cbmc --unwind 5 my_code.c

3.3 内核中的应用

四、TLA+

4.1 协议级验证

TLA+ 不验证 C 代码——验证算法/协议的抽象模型。

---- MODULE SimpleLock ----
VARIABLES lock, waiting

Acquire(t) ==
    /\ lock = 0
    /\ lock' = t
    /\ waiting' = waiting \ {t}

Release(t) ==
    /\ lock = t
    /\ lock' = 0
    /\ UNCHANGED waiting

Invariant == \A t1, t2 \in Threads : ~(InCS(t1) /\ InCS(t2) /\ t1 /= t2)
====

4.2 应用

五、KCSAN(Kernel Concurrency Sanitizer)

运行时数据竞争检测:

CONFIG_KCSAN=y

KCSAN 在运行时采样内存访问 → 发现 marked access 缺失 → 报告数据竞争。

BUG: KCSAN: data-race in func_a / func_b
  write to 0xffff... of 4 bytes by task 123:
    func_a+0x42/0x80
  read to 0xffff... of 4 bytes by task 456:
    func_b+0x18/0x60

5.1 与 herd7 的关系

互补,不替代。

六、rcutorture

modprobe rcutorture

对 RCU 进行暴力压力测试——多线程并发读/写/grace period → 检测语义违反。

不是形式化验证,但是 RCU 正确性的第一道防线。

七、实际案例

7.1 litmus test 发现的 bug

Paul McKenney 用 litmus test 发现多个内存序 bug:

7.2 CBMC 验证 RCU

cbmc --unwind 3 rcu_simplified.c --property "assert(readers_see_consistent_data)"

在简化模型上验证 RCU 的核心不变量。

八、工具对比

工具 抽象层次 穷举性 规模限制
herd7 内存操作 完全 很小(几行)
CBMC C 代码 有界 中等
TLA+ 协议/算法 完全 抽象模型
KCSAN C 代码 采样 整个内核

九、与测试的权衡

形式化验证不能替代测试:

十、小结


参考文献

工具


上一篇优先级反转 下一篇中断架构

同主题继续阅读

把当前热点继续串成多页阅读,而不是停在单篇消费。

2026-05-24 · os

【操作系统百科】Linux 内核内存模型

READ_ONCE、smp_mb、smp_store_release——内核并发代码的基石。本文讲 LKMM 的诞生、ordering 语义、cumulativity、address/data/control 依赖、marked vs plain access、litmus test 方法论。

2026-04-27 · os

【操作系统百科】内存回收

Linux 内存回收是 VM 最复杂的子系统之一。本文讲 active/inactive LRU、kswapd 与 direct reclaim、watermark 三线、swappiness 的真实含义、MGLRU 改造、memcg 回收与 PSI。

2026-04-28 · os

【操作系统百科】交换

swap 还值得开吗?本文讲 swap area 基础、swap cache、zram 压缩内存、zswap 前端压缩池、swappiness 的真实含义、容器里的 swap 策略,以及为什么现代 Android 全靠 zram 不靠磁盘。

2026-05-03 · os

【操作系统百科】Slab/SLUB 分配器

buddy 只管页粒度(4K+),内核大多数对象只有几十到几百字节。slab/SLUB 在 buddy 之上做对象级缓存。本文讲 slab 历史、SLUB 接手、SLOB 退场、kmem_cache、per-CPU cache、KASAN 集成。


By .