1、前言
数据结构中的链表在任何教程里面都是放在最前面讲解,这不仅仅体现它的重要性,而且说明了它的基础性。不说是地基,也能说是根葱,顶梁柱。而且在整个内核当中,无处不在。
记得在上大学的时候,学习数据结构链表,虽然用它写了很多程序,但是始终不晓得它的重要性在哪,更不知道它到底有何神通,用到何处。向左,向右,向前看,Linux要拐几个弯才来遇见(《遇见》),后来,终于在Linux中明白,有些地方一旦用了就忘不了。 双链表,吊炸天,落在我vim编辑code上。“爱你!”我轻声说。 如果当时我能看到你,现在也不会觉得那么相见恨晚(《后来》)^_^
言归正传,本博文Kernel3.10版本。揭开Linux双链表的面纱,领略大家的编码。
背景:kernel在2.1V后引入链表集合统一起来,目的就为了避免代码冗余。链表用途太广了,如果不统一起来,那么自己需要的时候,自己造一个,结果kernel内“百花齐放”,重复“造车轮”,因此现在要求,所有内核开发者应该使用如今的链表接口。
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>声明<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
>> 知识要传播,劳动要尊重! 受益于开源,回馈于社会! 大家共参与,服务全人类!
>> 本博文由my_live_123原创(http://blog.csdn.net/cwcmcw),转载请注明出处!
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>^_^<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
2、双链表结点数据类型定义
<linux/types.h>
struct list_head {
struct list_head *next, *prev;
};
其中,next域指向前驱结点,prev域指向后驱结点
2.1、不严格区分头尾结点
这里不像数据结构教程里那样严格区分头结点,尾结点和表结点。
解析:事实上,内核不过分区分头结点还是尾结点,整个链表是一个完整的环形,完全可以抛开头尾这些概念;只有有序链表,才加以区分;当对访问链表的顺序没有要求时,遍历链表仅仅需要从链表中任意一个结点开始,沿着指针逐个访问下一个(或者前一个,不区分头尾,其实没有方向@_@,因此下一个可以是next也可以是prev,千万别晕哦),直到重新回到起始的结点即可!因此,不需要特别的头或者尾结点,每个进程仅仅需要指向链表中某个结点的指针,就可以操纵链表了ÿ