仓库源文

.. Kenneth Lee 版权所有 2019-2020

:Authors: Kenneth Lee :Version: 1.0

软件飞线


最近在和一个研究所的同事交流,谈到把一个特性移到他们这里来做的问题,我提到这个 软件飞线太多,不适合独立拉出来给他们做。这位同事不能理解:什么是“飞线太多”。这 是一个架构问题,本文理一下这个逻辑。

构架设计和编码都是逻辑设计,都是“如果XXX,就YYY”。区别在于,这个逻辑是否成立, 编码可以让“计算机”进行测试,架构设计只能用“人脑”来进行测试。所以,架构设计领域 滥竽充数的人特别多,因为可以“运行复杂逻辑”的脑子很少,“构架代码”不能跑,不具有 可抽象性:代码是否正确,可以代理为:计算机是否输出正确结果。架构逻辑是否正确, 只能在脑子中一行行过。

所以,编码是工作在非常稳固的“计算机接口”上的。架构是工作在非常不可靠,需要人为 维护的“逻辑接口”上的。在编码上破坏这种人为维护的“逻辑接口”,我就称为“飞线”。这 和硬件PCB的飞线的概念是一样的:本来PCB已经把所有元器件如何互联都定义了,但越过 这个定义,直接在两个点之间直接连了一根导线。原来在PCB上想好的信号一致性,可靠性 ,应力,温度控制,干扰,防静电等等措施就不再对你有约束力。虽然可能你解决了一个 问题,但其他设计就不可靠了。

举一个现实的例子,以前的博文我聊过IOMMU的当前状态:硬件可以支持多个进程(pasid ),软件只能支持一个进程,但多进程正在上传。但我的驱动现在就要用。我们进行了这 样一个设计:

  1. 基本原则:内核使用设备内存使用dma api;进程使用设备内存使用iommu api(在本框 架内进行封装)

  2. 检测到内核没有pasid支持的时候,强制内核选择其中之一,另一方不支持

  3. (例外)在支持进程的时候,如果内核不得不使用内存,必须通过封装的iommu api接 口进行使用。

其他细节我先忽略,有了这个原则的实施。我的高层(架构)设计就可以进行很多其他设 计了,比如我可以做这样的设计:如果我在另一个模块中发现内核没有pasid支持,我可以 认为实施这个原则的模块传递过来的设备内存,一定是dma api分配的。

这个逻辑全部在文档或者在人脑中,编码者为了实施他的特性,很容易就破坏它。比如在 特定场合上,同时使用dma api和iommu api。虽然,很多时候我们会用自动化工具(包括 代码结构)去保护我们的架构策略,但对于复杂系统来说,你不可能都靠这种方法,而且 工具本身有工作量,靠工具制定的原则可能会变成架构负担的。这时,我们只能靠模块的 maintainer或者gate keeper去进行这种保护。这部分工作,就是系统的构架控制了。

而飞线,就是对这种保护的破坏。一个系统,如果飞线多了,架构控制就没有了。你失去 了系统中一个个可以被单独依赖的逻辑,构架设计就成了一句空话。因为它的基础没有了 。它只有每个具体情况的“如果”,没有大部分情况的“如果”。你拿到一片内存,你就知道 是个指针,它在不在物理内存中,设备是否可以访问,你能不能访问,你都不知道。你在 现在的平台上可以访问,换一个平台,换一个时间还能不能访问你都不知道。这怎么建逻 辑嘛。一旦系统成了这样,你想把一个模块拉出去给另一个团队做,这就完全没有可能了 。

很多人觉得架构设计和控制是不必要的,但在架构师眼中,一个个可依赖的逻辑和抽象被 消灭,是直接看得见的。不少人做设计,一副很务实的样子,上来就开始设计一个个具体 的流程,不控制最高一层逻辑,等设计完了,高一层的逻辑就没有了。这样的系统,后续 想加什么大特性,都不能指望,因为你实施任何措施,这个措施都没有可以依赖的逻辑。 就只能一点点试了,而且不保证一定行,这种到后期,要不就不开辟新市场或者应用场合 ,要不就只好拉分支,或者重新来了。

所以,做飞线不是不可以——在战地版本中做。同时,不要指望打完一场仗,战地版本还能 用下去。

附录1:一个实际的架构控制的交流邮件

我分享一个我实际工作中的架构交流邮件,让读者实际体会一下具体什么是架构面的逻辑控制:

    | XX,你好,
    | 我们最好不要碰到困难就想着躲。你还记得最初为什么要写文档的吗?
    | 逻辑是这样的:
    | 首先你碰到一个问题:close(fd)是异步的,在你close(fd)后,
    | 硬件q不一定会释放,这时你立即做open,可能就没有q可以用了。
    | 所以,你要强行把q的硬件放掉。所以你最早用flush来放硬件,
    | 但我拒绝掉了这个patch,因为这个破坏了逻辑,flush的作用是软硬件同步,
    | 没有人预期flush完了,会连硬件都丢失了的。
    | 所以我们的结论是我们会增加一个主动的ioctl(put_queue)。
    | 但这样就带来另一个问题:原来只要没有close(fd),
    | 就可以预期硬件一直在,但现在fd里多了一个状态,硬件可以不存在。
    | 这时其他所有API的行为应该是怎样的?这个状态机是什么?
    | 这就需要有个设计,否则系统的状态就成了一团乱麻,以后你想再增加逻辑,
    | 就很难想了。
    | 而你现在说直接给我代码,这个状态机有没有成为乱麻,我怎么知道呢?
    | 所以,你直接提交代码,其实就是让我来给你设计这个状态机。
    | 每个特性都是我来做设计,一个我忙不过来,另一个,
    | 我一直也无法把这个设计工作交托给你们啊。
    | 综上,还是写个文档来吧。

不知道读者是否可以从这个邮件理解,什么是架构看到的逻辑,和什么是架构设计和控制 ?