Debian架构研究
2017-07-12王洋
王洋
摘要:Debian的架构通过详细分析软件包的相关性来了解软件包之间的相互作用进行了研究。Debian中的依赖是广泛的,这使得其成为一个有趣的架构,但它们使得分析更为复杂。研究中提供了分层模式的分析,此模式基于如何使用它们将每个软件包分类为五个层之一。这些层也可以被可视化以给出应用如何被结构化的简明视图。使用这些视图,研究发现有新的架构子模式和反子模式,可以帮助开发人员创建和维护软件包。
关键词:Debian;架构;五层;子模式;反子模式
中图分类号:TP311 文献标识码:A 文章编号:1009-3044(2017)13-0075-03
1概述
为了有效地描述Debian的架构,本文提出了一套可以用来对软件包进行分类的模式。首先,软件包可以根据进入和离开依赖关系的数量被分类为分层模式或隐藏模式的一部分。一旦被发现是分层模式的一部分,该软件包可以进一步分类为特定层。本文还提出了两种自动分类技术,以提供属于每个模式的每层的软件包的数量。
属于应用层的软件包与其他层不同,该层内的软件包之间的依赖性可以提供关于特定应用如何被结构化的许多信息。结构化应用程序的不同方法通过五个子模式描述。这些子模式是由软件包维护者做出的设计选择。通过引人这些模式,我们可以向经验不足的维护者提供有关使用模式和避免模式的信息。
1.1可视化Debian软件包
Debian是一个拥有大量软件包的庞大系统,绘制有向图有助于直观的说明Debian软件包如何相互交互。要手动绘制和组织超过30000个软件包,具有120000个依赖关系是几乎不可能的,因此我们依靠软件来帮助可视化。我们从每个软件包中获取依赖性数据,然后将数据合并到一个文件中。数据从Wa-terloo大学的SWAG实验室进入LSEdit。LSEdit是一个图形可视化工具,用于查看,操作,查询,布局和大图聚类。但是,由于软件包的数量和依赖性,很难输出。
在这个不成功的可视化Debian的尝试之后,我们决定缩小并研究单个应用程序及其依赖关系。Frans Pop开发的一个名为debtree的工具提取了一个特定软件包的所有依赖,然后输出一个图。这些图是大而凌乱的,但是比尝试一次查看整个软件包集合更易于管理。可视化软件包和详细描述它们的依赖关系的功能允许我们理解使软件包运行的内部工作原理。这个程序被应用到各种其他软件包。我们仔细检查了其他20个软件包,注意到他们都共享两个基本的架构模式之一。
1.2分层模式
软件包可以分类到分层模式或隐藏模式中。属于分层模式的软件包是对整个应用程序有贡献的单个部分。我们发现,可以将包含在分层模式中的软件包分类为五个层:元包层,应用程序层,應用程序库层,特定目的库层和通用库层。
1.3隐藏模式
除了五个软件包层之外,还有一组额外的软件包不符合分层模型,我们将这些软件包标记为隐藏包。对于要被分类为隐藏包的软件包,它必须不具有对其他软件包的依赖性,也不具有来自任何软件包的依赖性。属于这个组的许多软件包只包含数据或文本。但是,也可能是这样的情况,软件包是一个轻量级的应用程序。事实上,Debian中很多软件包不包含单个依赖或引用。隐藏包是不与系统的其他软件包交互的独立软件包。
1.4软件包层的自动分类
为了研究Debian的整体组成,我们更详细地研究隐藏和五层,更具体地说,每个层的组成和它们如何相互交互。我们把整套Debian软件包分配给一个层或者作为一个隐藏包。
我们可以通过使用软件包的描述手动将软件包分类到五层中,但是手动分类超过30000个软件包是不可行的,因此我们寻求一种自动完成这个任务的方法。在手动分类的过程中,我们注意到许多相同的通用库被一遍又一遍地引用,同时,在应用程序库级别及以上的软件包很少被引用。这个发现影响到所有Debian软件包的In、Out、Transitive In和Transitive Out度的计数。软件包的In度是直接依赖它的其他软件包的数量。Out度计算对软件包的直接依赖的数量。Transitive In计算直接或间接依赖于它的软件包数。例如,如果软件包A依赖于软件包B,而软件包B依赖于软件包C,则软件包C将具有1的In度,但是传递In数为2。Transitive Out指的是需要安装以满足所有依赖关系的软件包的总数。我们使用两种方法来对软件包进行分类。第一种方法是通过简单的排序和过滤。这是一个特殊过程,其步骤如下:
1.通用库:
我们首先根据Transitive In计数对软件包的列表进行排序,因为我们观察到通用库被广泛引用。在大约500次计数时,程序包不再类似于通用程序包,因此我们决定在此时设置阈值。
2.隐藏包:
现在,我们开始识别隐藏包。这些是孤立的软件包,因此组合的In和Out度为1的软件包被标记。我们将In和Out度的阈值设置为l而不是0,是因为小型轻量级应用程序仍然依赖于标准c库以便运行。具有单个依赖关系的这些应用程序仍然被认为是隐藏,因为没有有意义的依赖结构。
3.元包和应用级别:
使用隐藏的方式,具有小于5的In计数和大于30的Transi-five Out计数的软件包将被认为是元包层或应用层的一部分。应用程序通常倾向于具有很少的引用,但是依赖于许多其他的软件包。元包和应用程序在顶层,因此依赖于应用程序、特定的和通用的函数库。因此,这些顶层软件包将始终具有比库软件包更大的Transitive Out计数。我们还决定将元包和应用程序级软件包组合为一个组,因为不经常遇到元包,此外,几乎不可能基于In/Out的度区分这两个组之间的差异。
4.特定目的库:
为了筛选特定目的库,我们寻找In度大于15或Transitive1n数超过100的软件包。从应用我们前面的三个步骤,我们现在剩下的包也具有小于500的Transitive In计数和小于30的Transitive Out计数。这是对特定目的库的描述,因为它们比通用库更少引用,通常具有较小的Out度。
5.应用程序库:
剩余的软件包现在标记为应用程序库。这些包具有小于15的In度和小于30的Transitive Out度。由于使用有限,应用程序库往往具有较小的In和Out度。
总的来说以上所描述的过程是特定的,并且仅进行以提供对每个包层的大小的估计。表1总结了软件包的In,Out,Tran—sitive In和Transitive Out度计数。大多数手动分类软件包似乎也使用点对点方法分类到同一层。
我们分组软件包的第二个技术是应用聚类算法到整个Debian软件包。Weka是一个开源工具,包含一组机器学习算法。我们使用其中一个可用的聚类算法帮助我们将软件包分类为层或隐藏。K均值是一种较好的机器学习算法,用于将数据集分割成k个单独的集群,其中每个集群中的实例彼此相似。在这个特定算法中的相似性度量被定义为两个实例之间的欧几里德距离。我们将簇数参数设置为5以对应于层数,然后让算法运行。具有5个簇的K均值聚类的结果显示于表2。由k均值产生的输出是5个软件包的集群,算法认为它们是彼此最相似的。Weka不输出软件包所属的集群。因此,为了提取K均值分配给每个软件包的集群,必须对源代码进行一些修改,添加的源代码体现出文本文件中的所有软件包的实例及其对应的集群。
从检查每个集群中的软件包的连接性,我们注意到每个集群中的一个共同的主题,类似于我们的点对点过程。使用与点对点方法相似的推理方式,将软件包层分配给集群,如下所示。具有高Transitive In度的软件包被聚集在一起,因此我们将这个簇标记为通用库的层。大多数软件包展现出零或非常少的连接性的集群被标记为隐藏。应用层软件包与具有大量高Transitive Out计数和低Transitive In计数的集群匹配。两个剩余的集群被选择为应用程序库或特定目的库。具有较高Out/Transitive Out计数和较低In/Transitive In的簇被标记为应用程序库层。具有相反特性的簇被标记为特定目的库。由K均值算法输出的簇的特性各自明显不同,因此使得每个簇表示一层更容易。
表2中的数字显示了Debian在软件包模式(和层)方面的组成。最引人注目的是Debian中超过一半的软件包是隐藏的。这些是与组的其余部分隔离的软件包,并且不包含任何有意义的依赖性。另一方面,Debian的另一半参与了最重的分层模式。在属于分层模式的软件包中,大多数是应用程序级别层的一部分。这表明Debian包含大量的应用程序软件,而不是支持软件包。虽然库文件通常在Debian中被引用,但是没有大量的文件。
有趣的是,点对点方法和K均值产生类似的结果,如表5.2,区别在于特定目的库计数,因为使用点对点几乎找到了10倍。聚类算法的工作方式可以解释为什么表示特定目的库的K均值聚类很小。该算法将类似的软件包集中在一起,因此我们在点对点方法中发现的许多特定目的库被认为更类似于其他集群中的软件包。无论如何,此分析提供了Debian的组成和用户可用的软件包类型的估计。
1.5应用子模式
分层和隐蔽模式描述了如何相对于整个软件集合来构造软件包。相比之下,本节中描述的模式仅处理应用程序级别的模式。这些模式是Debian维护者如何设计和布置特定应用程序的表现形式。因此,我们将称这些为子模式和反子模式。子模式是包装软件的通用解决方案,而反子模式展示了用于包装软件的另一种方法。
1.5.1应用子模式:共享
我们提供的第一个应用程序子模式是共享模式。这种模式发生在维护者从一个或多个被重用的软件包中导出部分时。节省空间是重要的,有时对于嵌入式或其他低资源机器是必要的。通常情况下,这些包名称以“common”结尾,因此我们将这个共享模式标记为这样共享模式背后的想法类似于创建库包,但规模较小。例如,库包通常适用于更广泛的受众,需要特殊的包装实践,以确保所有依赖包的效率无误。
1.5.2应用子模式:模块化
另一个子模式是模块化子模式。在这种模式中,应用程序被分成多个部分,其中每个部分在很大程度上是彼此独立的。当应用程序频繁更新时,Debian维护者需要确保应用程序的新添加项可以单独应用。一般来说,维护者必须尽可能模块化它们所包装的应用程序。
1.5.3應用反子模式:意大利面
当这种类似意粉的模式发生时,大量的交织依赖使得很难看到为什么特定的软件包被引用。这使得管理依赖关系变得困难,因为维护者需要很好地理解每个软件包的功能。维护者最初不计划具有意大利面依赖性。但是随着时间的推移,软件包的结构可能通过一系列更新和修订而演变成这种混乱的状态。在某种程度上,维护者可能需要重组软件包。
1.5.4应用反子模式:完全连接
应用程序的所有软件包都相互引用的依赖关系图通常不是很好的设计。如果应用程序中的每个软件包都依赖于每个其他软件包,则它应该只保留为单个软件包。从软件包描述中,每个phpgroupware应用程序包都有一个唯一的函数,并且看起来这个应用程序是模块化的,然而,依赖性使得这个模块化不能令人满意,因为一个软件包的安装需要安装其余软件包。
1.5.5应用反子模式:整体
还有一个反子模式,但它不能像其他一样可视化,这使得它难以识别。这是单片子模式,它适用于大型应用程序级包。从共享和模块化子模式我们发现,将一个更大的软件包分解成更小的子模式是一个好主意,并导致一个改进的结构。大型独立软件包违反了这个理念,因此它是一个反子模式。虽然整体对于不涉及软件包的人来说很难注意到,但是负责软件包的应该知道整体反子模式是什么时候出现的。
1.6小结
本文的目标是研究Debian的架构。开放源代码软件的用户基础庞大,可用的新软件包的数量正以惊人的速度增长。然而,在这种普及性之下,对于上传的软件包以及它们如何相互交互,存在理解不足的情况。在本文中,我们提出了这样的概念:软件包或者以隐藏模式单独存在,或者属于分层模式中的五个层之一。这些层是:元包层,应用程序层,应用程序库层,特定目的库层和通用库层。在Debian中,一半以上的软件包是隐藏的,因此没有对其他软件包的依赖。另一半形成了一个顶层的分层模式,这意味着大多数软件包被分组到应用程序层,而在库级别比较少。
将软件包分类到它们的层中,并且仅可视化每个层内的依赖性允许更容易理解的图。应用程序层中软件包的可视化很重要,因为我们获得了显示应用程序组织方式的简明图。在这种可视化中,删除了对低级库的自动依赖性,剩下的是来自开发人员的创建软件包的包装设计。我们以两个子模式和三个反子模式的形式呈现包装设计原则:共享,模块化,意面,完全连接和整体。经验丰富的软件包维护人员知道包装软件的最佳方法,但通过记录这些模式,我们希望帮助新开发人员生产更高质量的软件包,这些软件包不容易出错并且更易于升级。