Linux 内核链表
经过上一小节的分析,我们知道了传统链表的先天缺陷:没有将具体的数据从组织这些数据的逻辑结构中剥离,而Linux内核链表的思路,正是从一方面着手,追根溯源直抵病灶,彻底颠覆了传统链表:把传统链表中的“链”抽象出来,使之成为一条只包含前后指针的纯粹的双循环链表,这样的链表由于不含有特殊的数据,因此它实质上就是链表的抽象表示:
这样的只有前后两指针的纯粹的链表形式被称为Linux标准双向循环链表。当然,光是这样的一条链表是毫无意义的,就好比一根绳子,但是没有串上任何东西。下一步,就是将这条绳子“嵌入”一个具体的节点当中,比如:
这样,链表的逻辑就被单独地剥离开来了,所带来的好处是巨大的:我们可以定义针对内核链表的基本操作并将之运用到任何类型的节点中,因为此时我们对链表的操作已经完全与数据无关,所有操作统一针对Linux标准抽象链表,可以适用任何类型数据的节点
这样做的另一个好处是,使得复杂的数据结构背景变得更易受控,一个节点在系统中的关系网跟一个人在社交网络中的关系网类似,一个人不可能只单单处于某一个关系逻辑之中,比如你是某家公司的职工人员,同时你还是你们家族关系网中的一员,你也是某一家俱乐部的VIP会员,你还是一个业余乐队的成员,你还有N多的社会关系网络,如果一个节点也是有这样的众多背景,用传统的节点来表达的情况是这样的:
这个节点每增加一个“数据结构背景”,其节点就要多一对指针,要命的是,这些不断增加的指针会导致结构体的成员发生变化,从而使得其他的链表指针跟着发生变化,因此这是一种完全不可取的做法。
而Linux内核链表则完美地避免了这种情况(广告时间),因为任何情形下对链表的操作都是统一的,跟具体的节点无关,一个节点如果处在一个复杂的关系网之中,Linux内核链表也很容易就可以解决,只需要在节点中镶嵌更多的“小结构体”即可,如图所示。
总结起来,Linux内核链表的突出优点是:由于可以非常方便地将其标准实现(即“小结构”)镶嵌到任意节点当中,因而任何数据组成的链表的所有操作都被完全统一。另外,即使在代码的维护过程之中要对节点成员进行升级修改,也完全不影响该节点原有的链表结构。
既然Linux内核链表是一种统一的抽象的数据结构实现,那么在Linux源码中就有专门的已经写好的代码,实现了内核链表的初始化、插入、删除、遍历、移动等等,这些代码被保存在内核目录中的inlucde/btrfs/list.h中。