linux内核链表解析 初学者如何理解内核链表_华清远见.docxVIP

  • 13
  • 0
  • 约1.29万字
  • 约 19页
  • 2018-11-18 发布于天津
  • 举报

linux内核链表解析 初学者如何理解内核链表_华清远见.docx

linux内核链表解析 初学者如何理解内核链表_华清远见.docx

linux内核链表解析 初学者如何理解内核链表 linux内核链表对于大多数的初学者来讲,都是挺难的一部分,不容易搞懂。本篇文章就由华清远见为大家解析linux内核链表,初学者应该如何理解内核链表呢?请往下看! 在Linux内核中使用了大量的链表结构来组织数据,包括设备列表以及各种功能模块中的数据组织。这些链表大多采用在[include/linux/list.h]实现的一个相当精彩的链表数据结构。 很多linux下的源代码都会使用这个头文件,它里面定义了一个结构,以及定义了和其相关的一组函数,本文详细分析了3.14 内核中链表结构的实现,并通过实例对链表操作接口进行了测试。 一、 链表数据结构简介 链表是一种物理存储单元上非连续、非顺序的存储结构,数据元素的逻辑顺序是通过链表中的指针链接次序实现的。链表由一系列结点(链表中每一个元素称为结点)组成,结点可以在运行时动态生成。 使用链表结构可以克服数组链表需要预先知道数据大小的缺点,链表结构可以充分利用计算机内存空间,实现灵活的内存动态管理。但是链表失去了数组随机读取的优点,同时链表由于增加了结点的指针域,空间开销比较大。链表最明显的好处就是,常规数组排列关联项目的方式可能不同于这些数据项目在记忆体或磁盘上顺序,数据的存取往往要在不同的排列顺序中转换。链表允许插入和移除表上任意位置上的节点,但是不允许随机存取。链表有很多种不同的类型:单向链表,双向链表以及循环链表。链表可以在多种编程语言中实现。像Lisp和Scheme这样的语言的内建数据类型中就包含了链表的存取和操作。程序语言或面向对象语言,如C,C++和Java依靠易变工具来生成链表。 通常链表数据结构至少应包含两个域:数据域和指针域,数据域用于存储数据,指针域用于建立与下一个节点的联系。 按照指针域的组织以及各个节点之间的联系形式,链表又可以分为单链表、双链表、循环链表等多种类型,下面分别给出这几类常见链表类型的示意图: 1. 单链表 图1 单链表 单链表是最简单的一类链表,它的特点是仅有一个指针域指向后继节点(next),因此,对单链表的遍历只能从头至尾(通常是NULL空指针)顺序进行。 2. 双链表 图2 双链表 通过设计前驱和后继两个指针域,双链表可以从两个方向遍历,这是它区别 于单链表的地方。如果打乱前驱、后继的依赖关系,就可以构成二叉树;如果再让首节点的前驱指向链表尾节点、尾节点的后继指向首节点(如图2中虚线部 分),就构成了循环链表;如果设计更多的指针域,就可以构成各种复杂的树状数据结构。 3. 循环链表 循环链表的特点是尾节点的后继指向首节点。前面已经给出了双循环链表的示意图,它的特点是从任意一个节点出发,沿两个方向的任何一个,都能找到链表中的任意一个数据。如果去掉前驱指针,就是单循环链表。 二、 Linux 3.14内核链表数据结构的实现 链表数据结构的定义很简单(定义文件在linux-3.14-fs4412\include\linux\Types.h中): 和第一节介绍的双链表结构模型不同,这里的list_head没有数据域。在Linux内核链表中,不是在链表结构中包含数据,而是在数据结构中包含链表节点。list_head结构包含两个指向list_head结构的指针prev和next,由此可见,内核的链表具备双链表功能,实际上,通常它都组织成双循环链表。 在数据结构课本中,链表的经典定义方式通常是这样的(以单链表为例): struct list_node { struct list_node *next; ElemType data; }; 在Linux内核链表中,需要用链表组织起来的数据通常会包含一个 struct list_head成员, struct list_node { struct list_head list; ElemType data; }; 从下图中我们可以看到,这种通用的链表结构避免了为每个数据项类型定义自己的链表的麻烦。 图3 内核链表链表示意图 三、 链表操作接口 1. 声明和初始化 实际上Linux只定义了链表节点,并没有专门定义链表头,那么一个链表结构是如何建立起来的呢?让我们来看看LIST_HEAD(和LIST_HEAD_INIT这2个宏: 当我们用LIST_HEAD(my_list)声明一个名为t的链表头时,它的next、prev指针都初始化为指向自己,这样,我们就有了一个空链表. Linux用头指针的next是否指向自己来判断链表是否为空: 2. 插入/删除/合并 a) 插入 对链表的插入操作有两种:在表头插入和在表尾插入。Linux为此提供了两个接口: 因为Linux链表是循环表,且表头的next、prev分别指向链表中的第一个和最末一个节点,所以,list_add和l

文档评论(0)

1亿VIP精品文档

相关文档