当前位置:   article > 正文

linux内核中的链表

一、linux内核链表中,链表结构是如何建立起来的?如何构建空链表?

1.内核中的链表

linux内核链表与众不同,他不是把将数据结构塞入链表,而是将链表节点塞入数据,在2.1内核中引入了官方链表,从此内核中所有的链表使用都采用此链表,千万不要在重复造车轮子了!链表实现定义在<linux/list.h>,使用内核链表时,包含此文件。

1.1.传统的双向链表和内核中的双向链表的区别
  • 有个单独的头结点(head)
  • 每个节点(node)除了包含必要的数据之外,还有2个指针(pre,next)
  • pre指针指向前一个节点(node),next指针指向后一个节点(node)
  • 头结点(head)的pre指针指向链表的最后一个节点
  • 最后一个节点的next指针指向头结点(head)
    739465-20160603152514633-79080094.png

传统的链表有个最大的缺点就是不好共通化,因为每个node中的data1,data2等等都是不确定的(无论是个数还是类型)。linux中的链表巧妙的解决了这个问题,linux的链表不是将用户数据保存在链表节点中,而是将链表节点保存在用户数据中.linux的链表节点只有2个指针(pre和next),这样的话,链表的节点将独立于用户数据之外,便于实现链表的共同操作。

739465-20160603152538774-1651029360.png

1.2.链表基础数据结构

内核链表节点原型

  1. /* linux/types.h */
  2. struct list_head {
  3. struct list_head *next, *prev;
  4. };

gcc特有的语法支持,根据结构体成员和结构体,算出此成员所在结构体内的偏移量

  1. #define list_entry(ptr, type, member) \
  2. container_of(ptr, type, member)

这个宏没什么特别的,主要是container_of这个宏

  1. #define container_of(ptr, type, member) ({ \
  2. const typeof(((type *)0)->member)*__mptr = (ptr); \
  3. (type *)((char *)__mptr - offsetof(type, member)); })

这里面的type一般是个结构体,也就是包含用户数据和链表节点的结构体。

ptr是指向type中链表节点的指针

member则是type中定义链表节点是用的名字

比如:

  1. struct student
  2. {
  3. int id;
  4. char* name;
  5. struct list_head list;
  6. };
  • type是struct student
  • ptr是指向stuct list的指针,也就是指向member类型的指针
  • member就是 list
    ** 下面分析一下container_of宏: **
  1. // 步骤1:将数字0强制转型为type*,然后取得其中的member元素
  2. ((type *)0)->member // 相当于((struct student *)0)->list
  3. // 步骤2:定义一个临时变量__mptr,并将其也指向ptr所指向的链表节点const typeof(((type *)0)->member)*__mptr = (ptr);
  4. // 步骤3:计算member字段距离type中第一个字段的距离,也就是type地址和member地址之间的差
  5. // offset(type, member)也是一个宏,
本文内容由网友自发贡献,转载请注明出处:【wpsshop博客】
推荐阅读
相关标签
  

闽ICP备14008679号