Linux内核数据结构—链表

转载 2018年01月09日 00:00:00


            (点击上方蓝字,快速关注)

链表(循环双向链表)是Linux内核中最简单、最常用的一种数据结构。

内核中关于链表定义的代码位于: include/linux/list.h。list.h文件中对每个函数都有注释,这里就不详细说了。其实刚开始只要先了解一个常用的链表操作(追加,删除,遍历)的实现方法,其他方法基本都是基于这些常用操作的。


链表结构:

1. 链表的初始化

初始化是一个双向链表,还是环状的,这和stl中的list是一样的。下面是形成一个空链表,list作为头指针(不是头节点)

 


2. 访问数据

内核链表不同于普通链表的是,它是内嵌到数据对象中,这么说来,就是同类型的对象内部都嵌有这个链表,并且是通过这个链表穿针引线在一起,我们关心的是对象中的数据内容,那么究竟是如何通过对象内部的链表来访问其中的数据内容的呢?



宏定义转到:

还有一个:


从后往前一步步分析:

将0x0地址强制转换为TYPE*类型,然后取TYPE中的成员MEMBER地址,因为起始地址为0,得到的MEMBER的地址就直接是该成员相对于TYPE对象的偏移地址了。

所以该语句的功能是:得到TYPE类型对象中MEMBER成员的地址偏移量。 

对于container_of:

先看第一条:const typeof(((type *)0)->member)*__mptr = (ptr); 首先将0x0转换为TYPE类型的指针变量,再引用member成员,typeof(x)返回的是x的数据类型,所以typeof(((type*)0)->member)返回的就是member成员的数据类型,该语句就是将__mptr强制转换为member成员的数据类型,然后再将ptr赋给它。ptr本来就是指向member的指针;

说白了,就是定义一个member成员类型的指针变量,然后将ptr赋给它。

好,来看下一条语句:

先将__mptr强制转换为char*类型(因为char* 类型进行加减的话,加减量为sizeof(char)*offset,char占一个字节空间,这样指针加减的步长就是1个字节,实现加一减一。)实现地址的精确定位,如果不这样的话,假如原始数据类型是int,那么这减去offset,实际上就是减去sizeof(int *)*offset 的大小了。

所以整体意思就是:得到指向type的指针,已知成员的地址,然后减去这个成员相对于整个结构对象的地址偏移量,不就得到这个数据对象的地址么

最后看list_entry:

有了前面的剖析,好理解了,该宏定义作为右值,返回type类型对象的地址。

type->member,表明member是type中的成员,所以可以得知member是内嵌的链表,type则是对象指针,那么ptr是链表类型指针,并且是属于那个穿针引线的链表中的某一个链表节点,所有的对象结构都挂在ptr所在的链表上。

该宏定义可以返回ptr对应链表节点的对象的地址。关键是对应,找到的对象的地址是ptr这个链表所对应的那个对象的地址。ptr和member之间的关系就是,ptr是member类型的指针。

其实上面就是地址的强制转换,然后得到偏移量之类的,就是指针,而且上面有个特点,那就是跟结构体中的内存对齐无关。

 

3. 遍历链表(实际是得到指定链表节点对应的数据对象结构)

有了前面的定位某个结构地址,遍历就好办了。

得到第一个节点元素地址

上面传入的ptr是将各个type对象串起来的链表的头指针,ptr->next 就是该链表的第一个节点。上面返回值就是挂载在第一个节点上的对象地址。

对象结构就是像下面这样挂载在链表上:


 

访问第一个对象就是:


遍历所有数据对象就是:

 

 

4、添加元素



new元素添加到prev的后面,next的前面。


5、删除元素



6、替换元素



7、移动元素



单链表

引言:        数据结构中,很重要的一个结构就是链表。链表虽然简单,但却能很好的考查程序员的基本功,因此在很多面试、笔试中会直接或间接的考查它。下面就对链表进行系统的复习。 分析描述: ...
  • To_Be_IT_1
  • To_Be_IT_1
  • 2014年07月08日 19:49
  • 877

链表和

#include<stdio.h> #include<malloc.h> #define ok 1 #define error 0 typede...
  • stormily
  • stormily
  • 2018年02月13日 23:59
  • 18

链表的c语言实现以及根据linux内核中链表的实现过程

转自 : http://blog.csdn.net/lickylin/article/details/8010618 链表,就是用一组任意的存储单元存储线性表元素的一种数据结构。链表又分...
  • xiaoxianerqq
  • xiaoxianerqq
  • 2016年11月01日 18:12
  • 347

关于linux内核的数据结构——list_head

前言最近想看linux内核,发现看了两周,还没啥进展,恰恰有些基础的东西往往忘记,这里先记录下最简单的东西,以后多记录。...
  • qq_28282317
  • qq_28282317
  • 2016年09月10日 10:17
  • 315

单链表基本操作

//////////////////////////////////////////// //单链表的初始化,建立,插入,查找,删除。// //Author:Wang Yong ...
  • xyx19890816
  • xyx19890816
  • 2010年10月19日 22:22
  • 57039

循环链表的C++模板实现

  • 2010年01月05日 22:02
  • 4KB
  • 下载

《Linux内核设计与实现》——内部数据结构

一、链表  1、链表
  • Explorer_day
  • Explorer_day
  • 2014年11月10日 15:59
  • 977

内核数据结构之映射

映射也称之为关联数组,它是一组唯一键的集合,每个键与特定的值相关。一般支持至少三个操作: Add(key,value) Remove(key) value=Loo...
  • fuyajun01
  • fuyajun01
  • 2012年03月30日 23:56
  • 2173

单链表

链表是常见的动态存储方法, 链表定义:用一组任意的存储单元来存放线性表的节点,这组存储单元可以是连续的,也可以是非连续的。 结点包括数据域和指针域。             数据域是...
  • yanghuangsanguo
  • yanghuangsanguo
  • 2014年05月04日 16:30
  • 513

单链表

线性表的链式表示和实现       线性表的链式存储结构的特点是用一组任意的存储单元存储线性表的数据元素(这组存储单元可以是连续的,也可以使不连续的)。因此,为了表示每个数据元素ai与其直接后继数据元...
  • hyg0811
  • hyg0811
  • 2013年09月02日 20:28
  • 786
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:Linux内核数据结构—链表
举报原因:
原因补充:

(最多只允许输入30个字)