开发中接触Linux越来越多,休息放松之余,免不了翻看翻看神秘的Linux的内核。看到双向链表时,觉得挺有意思的,此文记下。

作为众多基础数据结构中的一员,双向循环链表在各种“教科书”中的实现是相当的标准和一致的。

大概就是下面这个样子:

 typedef struct node_tag{
//T data;
struct node_tag *prev;
struct node_tag *next;
}node;

当你需要某种类型的链表时,把数据成员之类的往节点里塞就是了。比如菜谱链表,里面就可以有宫爆鸡丁,酸辣粉,地三鲜,水煮鱼,麻辣鸡翅。。。

嗯,当你需要另外一种链表时,接着如法炮制,只要功夫深,几十上百也不是问题。有一部分人善于解决这类问题,它们叫做CP程序员(Copy-Paste),

不要问我为什么知道。C++模板在这点上能实现通用特性,但不在本次内容之列了。

  有着极客精神的Linux,在内核中肯定不会像上面这么做的。内核中有大量的数据结构需要使用双向链表,诸如进程、模块、文件。

难道要人去维护各种类型的双向链表?而且还是不能复用的链表。我想没多少人愿意把时间花在这种事情上吧。维护一种通用的不就好了。

链表节点,作为一个“连接件”,最本质的内容就是把一些对象链接起来,至于对象内部存储的数据,是可以不用知道的。

在include/linux/list.h文件中,就有使用这样的一个"连接件“:

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

和node_tag相比,少了数据部分。

list_head作为独立变量时,充当的是链表头的角色;如果作为结构体成员时,则是“连接件”的角色。

  在这样的实现方式下,要获得某种类型的链表,只需在宿主结构中声明一个list_head成员,还可以任意的取名;

关键是,链表操作只需以list_head为对象进行实现;剩下唯一的问题是,在遍历链表时,该如何获取宿主结构的首地址?

毕竟链表是用来装内容用的。这里利用编译器的一个小技巧就可以算出地址偏移

#define offsetof(s,m)   (size_t)&(((s *)0)->m)

有了list_head相对宿主结构首地址的偏移,和自身地址来个加减就可以得到宿主的首地址,接下该怎么操作就怎么操作了。

个人觉得这里面有面向对象的意思。抽取出共同的“连接件” list_head,链表操作也以list_head为对象进行设计,

除了要具体访问操作宿主结构之外,全部都是共性的东西。

Linux内核中的通用双向循环链表的更多相关文章

  1. C语言通用双向循环链表操作函数集

    说明 相比Linux内核链表宿主结构可有多个链表结构的优点,本函数集侧重封装性和易用性,而灵活性和效率有所降低.     可基于该函数集方便地构造栈或队列集.     本函数集暂未考虑并发保护. 一  ...

  2. Linux内核中的算法和数据结构

    算法和数据结构纷繁复杂,但是对于Linux Kernel开发人员来说重点了解Linux内核中使用到的算法和数据结构很有必要. 在一个国外问答平台stackexchange.com的Theoretica ...

  3. linux内核中链表代码分析---list.h头文件分析(一)【转】

    转自:http://blog.chinaunix.net/uid-30254565-id-5637596.html linux内核中链表代码分析---list.h头文件分析(一) 16年2月27日17 ...

  4. Linux内核中的GPIO系统之(3):pin controller driver代码分析

    一.前言 对于一个嵌入式软件工程师,我们的软件模块经常和硬件打交道,pin control subsystem也不例外,被它驱动的硬件叫做pin controller(一般ARM soc的datash ...

  5. [翻译] Linux 内核中的位数组和位操作

    目录 Linux 内核里的数据结构 原文链接与说明 Linux 内核中的位数组和位操作 位数组声明 体系结构特定的位操作 通用位操作 链接 Linux 内核里的数据结构 原文链接与说明 https:/ ...

  6. Linux内核中常用的数据结构和算法(转)

    知乎链接:https://zhuanlan.zhihu.com/p/58087261 Linux内核代码中广泛使用了数据结构和算法,其中最常用的两个是链表和红黑树. 链表 Linux内核代码大量使用了 ...

  7. Linux内核中的软中断、tasklet和工作队列具体解释

    [TOC] 本文基于Linux2.6.32内核版本号. 引言 软中断.tasklet和工作队列并非Linux内核中一直存在的机制,而是由更早版本号的内核中的"下半部"(bottom ...

  8. linux内核中socket的创建过程源码分析(总结性质)

    在漫长地分析完socket的创建源码后,发现一片浆糊,所以特此总结,我的博客中同时有另外一篇详细的源码分析,内核版本为3.9,建议在阅读本文后若还有兴趣再去看另外一篇博文.绝对不要单独看另外一篇. 一 ...

  9. Linux内核中的GPIO系统之(3):pin controller driver代码分析--devm_kzalloc使用【转】

    转自:http://www.wowotech.net/linux_kenrel/pin-controller-driver.html 一.前言 对于一个嵌入式软件工程师,我们的软件模块经常和硬件打交道 ...

随机推荐

  1. 理解virtual方法

    1.使用场景 virtual方法的使用场景:父类告诉子类,继承接口,修改实现,从而可以面向接口编程. non-virtual方法的使用场景:父类告诉子类,继承接口和实现,从而可以代码复用. 2.成员方 ...

  2. 7za 解压文件

    7za.exe x -aoa 完美国际补丁.7z 7za.exe x -aoa 完美国际补丁.7z -o"C:\Users\Admin\AppData\Local\Temp\完美国际补丁&q ...

  3. 04---XML编程整理

    一.XML概述       XML(eXtensible Markup Language),可扩展标记语言,       被设计的宗旨是传输数据,而非显示数据       W3C发布的,目前遵循1.0 ...

  4. iOS开发——数据持久化Swift篇&iCloud云存储

    iCloud云存储 import UIKit class ViewController: UIViewController { override func viewDidLoad() { super. ...

  5. iOS开发——高级技术&二维码功能的实现

    二维码功能的实现 ZBarSDK,一个比较优秀的开源项目,使用起来也很简单. ZBarSDK是一个开源的SDK,可从这里下载到源码,该SDK实现了识别和读取各种条形码,包括EAN-13/UPC-A, ...

  6. ERROR:_OBJC_CLASS_$_ADBannerView

    http://stackoverflow.com/questions/4127489/iads-integration-with-cocos2d You are getting that error ...

  7. visual studio 2013 有效序列号

    还没试过,可以参考下! visual studio 2013 有效序列号: BWG7X-J98B3-W34RT-33B3R-JVYW9

  8. 【转】SQL Server 2012 配置AlwaysOn(三)

    转载自:http://www.cnblogs.com/lyhabc/p/4682986.html 从0开始搭建SQL Server AlwaysOn 第三篇(配置AlwaysOn) 第一篇http:/ ...

  9. 关于Eclipse平台的使用和开发第一个SWT程序

    IBM把投入巨资开发的Eclipse作为一个开源项目捐献给了开源组织Eclipse.org Eclipse出色而有独创的平台特性,现在仍由IBM子公司OTI(主要从事Eclipse开发的人)继续领导着 ...

  10. 【区间选点问题】uva 10148 - Advertisement

    区间选点问题,即数轴上有n个闭区间[l1i, ri],取尽量少的点,使得每个区间内都至少有一个点. The Department of Recreation has decided that it m ...