浅析Linux链表(1)| 8月更文挑战

194 阅读2分钟

Linux 中的链表采用了数据与结点分离的实现方式。这样在进行遍历等操作的时候,就可以大大的提升效率。

struct list_head {
    struct list_head *next, *prev;
};

在这个结构体类型定义中, 只包含两个指向list_head结构的的指针prevnext,并没有数据成员,其主要作用就是嵌套在其它结构体类型的定义中起到链接作用。

而在需要链表组织的数据,只需要包含一个struct list_head成员就可以把数据链接起来。这种通用的链表结构避免了为每个数据项类型定义自己的链表的操作。

操作接口

初始化

#define LIST_HEAD_INIT(name) { &(name), &(name) }
​
#define LIST_HEAD(name) \
    struct list_head name = LIST_HEAD_INIT(name)
​
#define INIT_LIST_HEAD(ptr) do { \
    (ptr)->next = (ptr); (ptr)->prev = (ptr); \
} while (0)

LIST_HEAD(name)在声明的时候完成了链表的初始化,将链表的前后指针指向了自己,得到一个空链表。

INIT_LIST_HEAD(ptr)在运行时初始化链表。

……

\

优势:

Linux的内核链表的一个突出优点是:由于可以方便地将其标准实现(即“小结构体”)镶嵌到任意结点当中,因此任何数据组成的链表的所有操作都被完全统一。另外,即使在代码维护过程中要对结点成员进行升级修改,也完全不影响该结点原有的链表结构。

内核链表的整体结构分为数据域和指针域两部分。指针域分为头指针和尾指针,头指针指向前一个数据,尾指针指向下一个数据;而头结点则让整个链表产生循环关系。信息存储在堆空间里的存储形式如图3所示。

图3 数据存储状态示意图数据存储状态示意图

使用场景

  1. 在C语言程序中若想根据需要动态地分配和释放内存单元, 通常可以使用链表结构来组织数据;
  2. 可以在用户程序自定义的结构体类型中定义一个或多个list_head指针, 用于链接不同的链表。

参阅

\