嵌入式Linux-内核链表完全讲解.pdfVIP

  • 2
  • 0
  • 约3.95千字
  • 约 4页
  • 2017-07-28 发布于浙江
  • 举报
嵌入式Linux-内核链表完全讲解

Linux 内核链表完全讲解 1.linux 内核链表 linux 内核中有很多用的很经典的数据结构,链表就算其中之一。在Linux 内核中使用了大量的链表来组织其数据,其采用了双向链表作为其基本的数据结 构。Linux链表同样具有链表的共同属性:第一,链表都是由节点组成的。第二, 链表的节点和节点之间是由指针进行连接的。但是与我们传统的数据结构中所学 的双向链表又有着一些不同 (其不包含数据域)。其主要是Linux 内核链表在设 计时给出了一种抽象的定义。 采用这种定义有以下两种好处:1是可扩展性,2是封装。可扩展性指的是 内核是在发展中的,所以代码都不能写成死代码,要方便修改和追加。而将链表 常见的操作都进行封装,使用者可以只关注接口,不需关注实现。 分析内核中的链表我们可以做些什么呢?我们可以将其复用到用户态编程 中,以后在用户态下编程就不需要写一些关于链表的代码了,直接将内核中 list.h 中的代码拷贝过来用。下面我们通过分析传统链表的局限性引出内核链 表的讲解。 1.1、前述链表数据区域的局限性 我们讲解单链表时,发现由于只含有一个后向指针,不能前向移动,于是我 们引出了双向链表。双链表可以实现前向和后向的移动,操作更为便利。然而依 然有它的局限性。前面我们讲链表时,为了简便起见,结构体的数据区域都是以 整型数据int data为例的。然而在实际编程中,链接中的节点数据不可能这么 简单。数据区域的大小和类型也是因实际需求不同而多种多样的。 一般实际项目中的链表,为了方便管理,节点中存储的数据其实是一个结构 体,这个结构体中包含若干的成员,这些成员加起来构成了我们的节点数据区域。 1.2、解决思路:数据区封装为结构体由用户实现,通用部分通过调用函数实现 由于实际问题对节点的内部数据区域的需求 (大小和类型等)各不相同,从 而由节点构造的链表也是多种多样的。这就导致了不同程序中链表的总体构成是 多种多样的。这给我们构建底层内核链表的通用操作函数带来了麻烦——我们无 法通过一个泛性的、普遍适用的操作函数来访问所有的链表。这就意味着我们设 计一个链表就得写一套链表的操作函数 (节点创建、插入、删除、遍历······), 显然这降低了代码的可重用性。 那么我们能否找到一种对链表操作的通用性方法,来满足现实问题中链表的 多样性呢?正如前面所述,Linux链表同样具有链表的共同属性,虽然不同问题 所需的链表操作代码不能通用,需要单独编写,但是内部的思路和方法是相同的, 只是函数中与实际问题相对应的局部数据区域有所不同。(实际上链表操作是相 同的,而涉及到数据区域的操作就有不同) 鉴于以上2点:我们的想能不能找到一种办法把所有链表中操作方法里共同 的部分提取出来用一套标准方法实现,然后把不同的部分留着让具体链表的实现 者自己去处理,通用的部分则通过调用函数的方式来实现。 1.3、内核链表的设计思路 Linux 内核就是采用了以上的思路来实现内核链表的。内核链表中自己实现 了一个纯链表 (纯链表就是没有数据区域,只有前后向指针)的封装,以及纯链 表的各种操作函数 (节点创建、插入、删除、遍历······)。这个纯链表本身没 法直接使用,它类似于一个半成品,作为核心提供给我们调用来实现自己的具体 链表。 内核链表是一个双向链表,但是与普通的双向链表又有所区别。内核链表中 的链表元素不与特定类型相关,具有通用性。下图为普通链表与内核链表区别的 示意图。 普通链表与内核链表的比较 normal list展示的是普通链表的结构,kernel list展示的是内核链表的 结构。head是链表头,p1,p2,p3是链表节点。从图中可以看出普通链表的p1 的next指针是指向的结构体p2的地址,p2的pre指针指向p1结构体的地址。 而内核链表的p1的next指向的是p2结构体中包含pre和next部分的地址,的 p2的pre指向的是p1结构体中包含pre和next部分的地址。依此类推,这就 是区别。内核数据区域的结构不与特定类型结构相关,任何结构体都可通过内核 的添加成为链表中的节点。 1.4、list.h文件简介 内核中核心纯链表的实现在include/linux/list.h文件中 list.h 中就是一个纯链表的完整封装,包含节点定义和各种链表操作方法。 (1)首先看到的是下面这句代码,这句代码是宏定义与用{}对结构体成员

文档评论(0)

1亿VIP精品文档

相关文档