Linux内核中的通用双向循环链表
开发中接触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内核中的通用双向循环链表的更多相关文章
- C语言通用双向循环链表操作函数集
说明 相比Linux内核链表宿主结构可有多个链表结构的优点,本函数集侧重封装性和易用性,而灵活性和效率有所降低. 可基于该函数集方便地构造栈或队列集. 本函数集暂未考虑并发保护. 一 ...
- Linux内核中的算法和数据结构
算法和数据结构纷繁复杂,但是对于Linux Kernel开发人员来说重点了解Linux内核中使用到的算法和数据结构很有必要. 在一个国外问答平台stackexchange.com的Theoretica ...
- linux内核中链表代码分析---list.h头文件分析(一)【转】
转自:http://blog.chinaunix.net/uid-30254565-id-5637596.html linux内核中链表代码分析---list.h头文件分析(一) 16年2月27日17 ...
- Linux内核中的GPIO系统之(3):pin controller driver代码分析
一.前言 对于一个嵌入式软件工程师,我们的软件模块经常和硬件打交道,pin control subsystem也不例外,被它驱动的硬件叫做pin controller(一般ARM soc的datash ...
- [翻译] Linux 内核中的位数组和位操作
目录 Linux 内核里的数据结构 原文链接与说明 Linux 内核中的位数组和位操作 位数组声明 体系结构特定的位操作 通用位操作 链接 Linux 内核里的数据结构 原文链接与说明 https:/ ...
- Linux内核中常用的数据结构和算法(转)
知乎链接:https://zhuanlan.zhihu.com/p/58087261 Linux内核代码中广泛使用了数据结构和算法,其中最常用的两个是链表和红黑树. 链表 Linux内核代码大量使用了 ...
- Linux内核中的软中断、tasklet和工作队列具体解释
[TOC] 本文基于Linux2.6.32内核版本号. 引言 软中断.tasklet和工作队列并非Linux内核中一直存在的机制,而是由更早版本号的内核中的"下半部"(bottom ...
- linux内核中socket的创建过程源码分析(总结性质)
在漫长地分析完socket的创建源码后,发现一片浆糊,所以特此总结,我的博客中同时有另外一篇详细的源码分析,内核版本为3.9,建议在阅读本文后若还有兴趣再去看另外一篇博文.绝对不要单独看另外一篇. 一 ...
- Linux内核中的GPIO系统之(3):pin controller driver代码分析--devm_kzalloc使用【转】
转自:http://www.wowotech.net/linux_kenrel/pin-controller-driver.html 一.前言 对于一个嵌入式软件工程师,我们的软件模块经常和硬件打交道 ...
随机推荐
- oracle查询前10条记录
select * from table_name where rownum<11;
- JSON 之FastJson解析
http://blog.sina.com.cn/s/blog_7ffb8dd501013qas.html 一.阿里巴巴FastJson是一个Json处理工具包,包括“序列化”和“反序列化”两部分,它具 ...
- Android下得到APK包含信息
很多情况下,我们需要通过APK文件来得到它的一些信息. (此时此APK不一定被安装了) 0. 基础知识:可以通过android.content.Context的方法 getPackageManager ...
- nginx,linux压力测试工具webbench
webbench最多可以模拟3万个并发连接去测试网站的负载能力,个人感觉要比Apache自带的ab压力测试工具好,安装使用也特别方便. 1.适用系统:Linux 2.编译安装: 1. wget htt ...
- jquery 源码分析学习地址
http://www.ccvita.com/121.htmljQuery工作原理解析以及源代码示例http://www.cnblogs.com/haogj/archive/2010/04/19/171 ...
- STL——迭代器的概念
迭代器是一种抽象的设计概念,现实程序语言中并没有直接对应于这个概念的实物. 1 迭代器设计思维——STL关键所在 不论是泛型思维或STL的实际运用,迭代器都扮演这重要的角色.STL的中心思想在于:将数 ...
- 【ZT】修复iCloud中查找我的iPhone、查找我的iPad无法显示地图的方法
http://blog.sina.com.cn/s/blog_4ff28d30010118cm.html 进入C:\Windows\System32\drivers\etc在hosts文件里加入如下地 ...
- 三、Socket之UDP异步传输文件-多文件传输和文件MD5校验
本文接着上一篇文章二.Socket之UDP异步传输文件,在上一篇文章的基础上实现多文件的传输和文件传输完成后进行完整性校验. 要实现多文件的传输,必须要对文(2)中发送文件的数据格式进行改进,必须加入 ...
- PHP中的可变参数函数和可选参数函数
1)可选参数函数.例如: <?phpfunction add($var1,$var2,$var3=0,$var4=0){ return$var1+$var2+$var3+$var4;}echo ...
- CSS选择器优先级
1.类的覆盖顺序和应用的时候引用的顺序没关系,覆盖顺序取决于类定义的顺序 例如: .a{ color:red } .b{ color:green } 由于b晚于a定义,所以b覆盖a,反 ...