仓库源文

.. Kenneth Lee 版权所有 2019-2020

:Authors: Kenneth Lee :Version: 1.0

一个逻辑空间控制的例子:uacce生命周期管理


等不了SVA的进展,最近我们的兄弟开始上传WarpDrive的内核实现(uacce)了。内核 Maintainer Greg K. H.对其中一个地方提了如下意见:Greg Kroah-Hartman: Re: [PATCH v2 2/2] uacce: add uacce driver。

有兄弟看不懂这个意见是什么意思。我把这个作为一个例子,一方面解释Greg是什么意思 ,另一方面说明一下,如何在设计中控制自己的逻辑空间。

我们最初定义uacce这个对象,目的不是创建一个设备,而是定义一个“接口”:你有一个加 速器,这个加速器可以提供特定的用户接口,我们把控制这个接口的数据结构综合在一个 地方,就叫struct uacce。所以uacce->dev最初就叫dev,因为这是它的backup device, 而不是它的parent device,因为它本来就不是一个device,不属于设备名称空间的一部分 。

但为了暴露uacce的接口到用户态,我们创建了cdev,cdev要求背后有backup device。这 个device就不可能是那个加速器的device,因为那个device已经被device model管理了, 里面有自己的管理模型。所以我们在uacce中再创建了一个device,纯为了支撑cdev的模型 而已。

但按照惯例,我们的device和uacce综合在一起,uacce就变成一个device了。所以Greg提 了一个意见:“你的uacce就不应该叫uacce,而应该叫uacce_device”。我们也接受了,这 就意味了,我们整个名称空间的定义就修改了,uacce不再是一个“接口”,而是一个接受 device生命周期管理的设备对象。我们未来需要认为,某个加速器的驱动,如果注册为一 个uacce,本质就是为自己创建了一个虚拟的子设备,这个子设备叫uacce_device。

那么uacce_device就受Linux Device Model的直接控制了,它的生命周期管理就应该遵循 Linux Device Model的原则(基于refcount决定资源的最后释放)。

在这种情况下,我们在uacce_device中又内联了一个cdev对象进去,这个对象也有自己的 refcount,也有它自己的生命周期管理的。这两个流程是无法总保持一致的,我们总会出 现cdev接口已经放弃了,但暂时因为某个device管理流程的控制,uacce_device一时不能 释放的情形。这种情形现在还没有发生,但我们不能认为它就不会发生了。我们为长远着 想,从一开始就不能让这种情形发生。

Greg这种经验老道的,一眼就能看破这种破绽,估计也是看多了。他的要求是,要不你内 联device,变成一个uacce_device,要不你内联cdev,变成一个uacce_cdev,不能同时拥 有这两个身份。大部分Linux Kernel核心Maintainer都有这种能力,这其实就是架构控制 的能力。他们不是在关心你的代码现在能不能跑,而是你的代码能生存多久。如果你不知 道为什么现代操作系统这么难开发,也许这里能看到一点端倪。

我们要能对上这样的讨论,就有必要总从整个逻辑空间的自恰的角度来考量这些问题,而 不能用眼前的代码有没有问题来想问题。每个外部接口的修改,都要和原始的名称空间定 义对照,保证逻辑一直是通的。否则就会鸡同鸭讲,半天都对不上号。对方让你修改什么 ,你就仅仅修改那一个地方,其他地方的概念没有跟上,这样的交流是长久不了的。你要 接受对方一个意见,要从概念空间一致开始分析,这样所有需要调整的接口和实现都会跟 上,而不是越改越偏离。