在任何相互依赖的系统中,基本上都有两种选择。抽象和集成。(我故意不使用技术术语)。使用Abstraction,您的意思是,当您调用API时,尽管该API背后的代码可能会更改,但结果始终是相同的。例如,当我们打电话时,我们fs.open()
不在乎它是网络驱动器,SSD还是硬盘驱动器,我们总是会得到一个打开的文件描述符,我们可以用它来处理。通过“集成”,目标是提供一种“最好”的做事方式,即使方式发生变化。例如,对于网络共享而言,打开文件可能与对磁盘上文件而言不同。这两种方式在现代Linux桌面中都得到了广泛的使用。
从开发人员的角度来看,这是一个“适用于任何版本”或“适用于特定版本”的问题。OpenGL是一个很好的例子。大多数游戏都设置为可使用特定版本的OpenGL。是否从源代码编译都没有关系。如果该游戏是使用OpenGL 1.1编写的,并且您试图使其在3.x上运行,那么您将不会过得很开心。在频谱的另一端,无论如何,某些呼叫都有望正常工作。例如,我想打电话给fs.open()
我,不要在乎我使用的内核版本。我只想要一个文件描述符。
每种方式都有好处。集成以向后兼容为代价提供了“较新的”功能。虽然抽象提供了对“较新”调用的稳定性。尽管重要的是要注意这是优先事项,而不是可能性。
从公共角度来看,没有非常好的理由,抽象在复杂系统中总是更好。例如,假设是否fs.open()
根据内核版本而有所不同。然后,一个简单的文件系统交互库将需要维护数百种不同的“打开文件”方法(或可能的块)。当新的内核版本问世时,您将无法“升级”,您将不得不测试所使用的每个软件。内核6.2.2(伪)可能会破坏您的文本编辑器。
对于某些实际示例,OSX往往不关心破坏用户空间。他们的目标是更频繁地“整合”而不是“抽象”。在每次主要的OS更新中,事情都会中断。这并不是说一种方法比另一种更好。这是一个选择和设计的决定。
最重要的是,Linux生态系统中充斥着很棒的开源项目,人们或团队在空闲时间从事该项目,或者因为该工具非常有用。考虑到这一点,第二个开始变得不再有趣,而是开始成为PIA,那些开发人员将前往其他地方。
例如,我向提交了补丁BuildNotify.py
。不是因为我无私,而是因为我使用了该工具,并且想要一个功能。这很容易,所以这里有一个补丁。如果它很复杂或麻烦,我不会使用BuildNotify.py
,我会发现其他东西。如果每次出现内核更新时,我的文本编辑器都崩溃了,那么我将使用其他操作系统。我对社区的贡献(无论多么小)将不会继续存在或不存在,依此类推。
因此,设计决定是对抽象的系统调用进行的,因此当我这样做时fs.open()
,它就起作用了。这意味着要保持fs.open
长期fs.open2()
流行。
从历史上看,这通常是POSIX系统的目标。“这是一组调用和期望的返回值,您可以找出中间值。” 再次出于便携性原因。为什么Linus选择使用这种方法是他大脑的内在原因,所以您必须让他确切地知道为什么。但是,如果是我,我会选择抽象而不是复杂系统上的集成。