LWN: 运行时的检查功能!

关注了就能看到更多这么棒的文章哦~

The runtime verification subsystem

By Jonathan Corbet
June 7, 2021
DeepL assisted translation
https://lwn.net/Articles/857862/

在过去 15 年左右的时间里,realtime project 一直是 kernel 中许多创新的来源。不仅如此,更广义的实时社区(realtime community)也在做着许多有趣的工作,这些工作已经不仅仅是局限于确保响应的实时确定性的范畴了。其中一个例子是 Daniel Bristot de Oliveira 的 runtime verification patch set,可以监控内核来确保它的行为符合人们的期望。

内核社区中 realtime 相关的开发的目标是让生产系统(production system)要具有确定性(determinism),做了很多实事,但同时也有一个活跃的学术社区也在专注于 realtime 的工作。学术界的开发者经常奋力想与 kernel 这类项目达成有效的合作,但 kernel 性能、质量回归(regression)以及可维护性的关注导致了许多聪明想法无法落地。因此,有很多优秀的学术领域工作得花很长时间才能进入生产系统(如果最终真的被接受的话)。

想象一个绝对不允许错过实时性要求的系统,比如核反应堆控制器、喷气式客机的飞行控制系统,或者播放重要足球比赛的电视机中的图像处理器。在这种情况下,最好能确保系统总是在预定时间内对事件做出反应。如果仅仅感觉是它似乎及时响应了,这并不能给出确定的保证。

要达到更高的保证水平,一种方法是对此系统建立一个 formal model,用数学方法证明该模型能给出预期的结果,然后用可以想象到的各种情况来验证这个 model。这种方法是可行的,但也有它的困难:要确保 model 与真实系统能匹配,本身就是一个挑战。而且即使模型是完美的,几乎可以肯定这种 model 对于穷尽测试(exhaustive testing)来说都太慢了。现实世界中的系统复杂性使得这种方法肯定是不切实际的。

Runtime verification

runtime verification patch 采取了一种不同的方法。开发人员可以创建一个高抽象的模型(high-level model),用来描述系统可能处于的状态,以及在事件发生并得到处理时进行的状态转换。然后,这些 verification 代码会监控 kernel,确保系统确实按照预期行为在运行。如果在运行的系统中发现了问题,那么要么是 model 中存在错误,要么是系统中存在错误。无论如何,修复这个问题都会提高我们对系统能正确运行的信心。

在跟代码一起的 documentation patch 中描述了这个机制的用法,下面的例子就是编者从那里无耻地直接借来的。第一步,先要把自己对系统某个行为的模型给表达出来,所举的例子是 CPU 是否可以被抢占(preempted)—— 这是 realtime 研究人员经常会感兴趣的一个问题。这个 model 是用 DOT 语言描述的,因此可以很容易利用 Graphviz 来展示出来:

[Graphviz 输出]

在 preemptive 状态下,一个 CPU 就可以被更高优先级的任务抢占。preempt_disable 事件则使 CPU 进入 non_preemptive 状态,也就是不可以再发生抢占。preempt_enable 则使 CPU 返回到 preemptive 状态。在 non_preemptive 状态下的 sched_waking 事件会让 CPU 一直保持在这个状态。

漂亮的图表对于学术论文(或 LWN 文章)总是很有好处的,但当需要验证 kernel 是否真的像模型中描述的那样来运行时,它们的作用就很有限了。不过,如果这个 model 能够被用来生成帮助验证的代码的话,情况就大不一样了。patch set 中的一部分就是一个 dot2k 工具,它会读取 DOT 描述文件,输出一套 template 代码,可用来进行实际测试。然而,还需要先做一些工作来将这个产出物跟 kernel 联动起来。

Connecting the model to the kernel

dot2k 生成的模板代码包含了 model 中描述的状态和事件的定义,这是我们后续操作的前提:

enum states {
    preemptive = 0,
    non_preemptive,
    state_max
};
enum events {
    preempt_disable = 0,
    preempt_enable,
    sched_waking,
    event_max
};

根据这些信息,就可以建立一个状态机来匹配这个 model 了。此外还生成了一些 stub 函数,每当预先定义好的事件发生时,就会在 kernel 中调用这些 stub 函数,例如 preempt_disable 事件相应的 stub 函数就是这个:

void handle_preempt_disable(void *data, /* XXX: fill header */)
{
    da_handle_event_wip(preempt_disable);
}

开发者需要把这些函数原型补充完整,能跟这些函数被调用的方式吻合。反过来又取决于它是如何被合并到运行中的内核中的。这里有相当大的灵活性,几乎所有能使内核在响应相关事件时调用该函数的机制都可以使用。当然,最常见的情况似乎就是 tracepoint 了,这个机制早就存在,也是用来告诉大家我们感兴趣的事件发生了。内核在 preempt 被禁用时已经准备好了一个 tracepoint,名为 "preemption_disable",除了标准的 tracepoint 能提供的参数之外,还额外提供了两个参数,名为 ip 和 parent_ip。如果我们的 handle_preempt_disable() 函数要想跟这个 tracepoint 绑定起来,那么其原型就必须是这样的:

void handle_preempt_disable(void *data, unsigned long ip, unsigned long parent_ip);

其他的那些 stub 函数也必须用类似的方式来修改好。然后开发者必须把 handler 函数和它们各自对应的 tracepoint 关联起来,dot2k 提供的 template 让这个过程变得很简单:

#define NR_TP   3
struct tracepoint_hook_helper tracepoints_to_hook[NR_TP] = {
  {
    .probe = handle_preempt_disable,
    .name = /* XXX: tracepoint name here */,
    .registered = 0
  },
  /* ... */
};

通过在这里填写好相关的 tracepoint 的名字,就可以把 handler 函数加载上去。这个 template 中还提供了启动和停止 model 的函数,用来处理那些需要额外的初始化或清理动作的情况。对于这个简单的 model 来说,不需要修改这些函数。最后,dot2k 会生成两个 tracepoint 用来监测此 model 中的 event 和 error。

Running the model

接下来把生成的代码加载到 kernel 中,很可能是通过 loadable module 方式加载的。在一个启用了 runtime verification 的内核中,/sys/kernel/tracing 目录下中会有一个新的目录(名为 rv),其中有一组用来设置的文件,可以用来打开或关闭某个 model。也可以配置 "reactors",也就是在系统的行为与 model 所说的不一致时来执行一些动作。默认情况是什么都不做,也就是虽然在这种情况下 "error" tracepoint 会被触发,也不会做什么额外动作。这里可以换成比如说用 printk() 记录一条 message,或者如果我们对系统这种错误行为非常不满意时,可以直接让系统 panic。

realtime 的研究人员可以使用这种机制来检查他们的内核行为模型是否与现实相符。但不难想象,runtime verification 功能可能可以用在其他很多场景之中。比如可以用来监控系统的安全性,确保没有进程在意料之外的地方进入了特权状态。而另一个很明显的应用场景就是 regression testing(回归测试),各种内核子系统如果有了比较完善的 model,就可能可以在被用户看到某些偶发错误之前就先检测出来。使用 DOT 来定义模型的话,可以很容易用来放在描述 kernel 的预期行为的文档之中。

不过,第一步是要让这个功能进入内核。到目前为止,还没有很多 review 意见,所以看来还没有多少人 review。这个附加功能不会打扰到任何不使用此功能的用户,因此 runtime verification 功能在 review 时应该不会受到过高标准的责难,因此这个工作还是可能会被合并的。在那之后就可能会有一些有趣的应用被它引发出来。

全文完
LWN 文章遵循 CC BY-SA 4.0 许可协议。

欢迎分享、转载及基于现有协议再创作~

长按下面二维码关注,关注 LWN 深度文章以及开源社区的各种新近言论~

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值