1. 普通单链表

2. 内核链表

上图是本人从其他博客盗来的,差点被糊弄过去。

下图是本人自己用KeyNote画的(唉!!画图真的是让人心好累啊!!)。

差异是不是很明显啊?!

Read The Fucking Source Code

1. 初始化

/* include/linux/types.h */
struct list_head {
struct list_head *next, *prev;
}; /* include/linux/list.h */
/*××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××*/
// 一. 如何初始化一个链表,初始化后的链表是什么鸟样?
// 链表初始化的3个方法:
// 1.
#define LIST_HEAD_INIT(name) { &(name), &(name) }
// 使用示例: struct list_head test_list = LIST_HEAD_INIT(test_list); // 2.
#define LIST_HEAD(name) \
    struct list_head name = LIST_HEAD_INIT(name)
// 使用示例: LIST_HEAD(module_bug_list); // 3.
static inline void INIT_LIST_HEAD(struct list_head *list)
{
    list->next = list;
    list->prev = list;
}
// 使用示例: struct list_head test_list;
        INIT_LIST_HEAD(&test_list);
/*××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××*/

就连一个链表的初始化都想的这么周到!!真屌!!

初始化后,链表就是的鸟样:

2. 插入

/*
* Insert a new entry between two known consecutive entries.
*
* This is only for internal list manipulation where we know
* the prev/next entries already!
*/
#ifndef CONFIG_DEBUG_LIST
static inline void __list_add(struct list_head *new,
struct list_head *prev,
struct list_head *next)
{
next->prev = new;
new->next = next;
new->prev = prev;
prev->next = new;
}
#else
extern void __list_add(struct list_head *new,
struct list_head *prev,
struct list_head *next);
#endif /**
* list_add - add a new entry
* @new: new entry to be added
* @head: list head to add it after
*
* Insert a new entry after the specified head.
* This is good for implementing stacks.
*/
static inline void list_add(struct list_head *new, struct list_head *head)
{
__list_add(new, head, head->next);
} /**
* list_add_tail - add a new entry
* @new: new entry to be added
* @head: list head to add it before
*
* Insert a new entry before the specified head.
* This is useful for implementing queues.
*/
static inline void list_add_tail(struct list_head *new, struct list_head *head)
{
__list_add(new, head->prev, head);
}
/**
* list_add 和 list_add_tail的区别是:
* list_add 始终是在链表头后的的第一个位置进行插入:例如链表:head --> 数据1 --> 数据2 --> 数据3,插入新元素后:head --> new --> 数据1 --> 数据2 --> 数据3
* list_add_tail 始终实在链表末尾插入新元素:例如链表:head --> 数据1 --> 数据2 --> 数据3,插入新元素后:head --> 数据1 --> 数据2 --> 数据3 --> new
*/
/**
* 仔细分析上述函数,可以发现其函数抽象的巧妙。
* __list_add 接收三个参数:分别是new, prev, next。任何位置的双链表插入操作,只需这3个参数。那么new元素一定是在prev和next之间进行插入。
* 所以很明显:list_add是在head和head->next之间插入,那就是链表的第一个元素。
* list_add_tail实在head->prev和head之间插入,那就是链表的最后一个元素。
*/

3. 删除

/*
* Delete a list entry by making the prev/next entries
* point to each other.
*
* This is only for internal list manipulation where we know
* the prev/next entries already!
*/
static inline void __list_del(struct list_head * prev, struct list_head * next)
{
next->prev = prev;
prev->next = next;
} /**
* list_del - deletes entry from list.
* @entry: the element to delete from the list.
* Note: list_empty() on entry does not return true after this, the entry is
* in an undefined state.
*/
#ifndef CONFIG_DEBUG_LIST
static inline void __list_del_entry(struct list_head *entry)
{
__list_del(entry->prev, entry->next);
} static inline void list_del(struct list_head *entry)
{
__list_del(entry->prev, entry->next);
entry->next = LIST_POISON1;
entry->prev = LIST_POISON2;
}
#else
extern void __list_del_entry(struct list_head *entry);
extern void list_del(struct list_head *entry);
#endif /**
* 上述代码中存在两个宏,在include/linux/poison.h中的定义如下:
*/
/*
 * These are non-NULL pointers that will result in page faults
 * under normal circumstances, used to verify that nobody uses
 * non-initialized list entries.
* 是非空指针,在正常情况下会导致 page faults,用来验证没有人使用未初始化的链表项。
 */
#define LIST_POISON1  ((void *) 0x00100100 + POISON_POINTER_DELTA)
#define LIST_POISON2  ((void *) 0x00200200 + POISON_POINTER_DELTA) /*
* __list_del_entry 和 list_del 的却别是显而易见的。
*/

  

  至此,内核链表有了本质的认识,那么对于其他的链表操作的分析是非常容易的。

深入分析Linux内核链表的更多相关文章

  1. 深入分析 Linux 内核链表--转

    引用地址:http://www.ibm.com/developerworks/cn/linux/kernel/l-chain/index.html 一. 链表数据结构简介 链表是一种常用的组织有序数据 ...

  2. 深入分析 Linux 内核链表

    转载:http://www.ibm.com/developerworks/cn/linux/kernel/l-chain/   一. 链表数据结构简介 链表是一种常用的组织有序数据的数据结构,它通过指 ...

  3. Linux 内核链表的使用及深入分析【转】

    转自:http://blog.csdn.net/BoArmy/article/details/8652776 1.内核链表和普通链表的区别 内核链表是一个双向链表,但是与普通的双向链表又有所区别.内核 ...

  4. C语言 Linux内核链表(企业级链表)

    //Linux内核链表(企业级链表) #define _CRT_SECURE_NO_WARNINGS #include<stdio.h> #include<stdlib.h> ...

  5. Linux 内核链表

    一 . Linux内核链表 1 . 内核链表函数 1.INIT_LIST_HEAD:创建链表 2.list_add:在链表头插入节点 3.list_add_tail:在链表尾插入节点 4.list_d ...

  6. linux内核链表分析

    一.常用的链表和内核链表的区别 1.1  常规链表结构        通常链表数据结构至少应包含两个域:数据域和指针域,数据域用于存储数据,指针域用于建立与下一个节点的联系.按照指针域的组织以及各个节 ...

  7. Linux 内核 链表 的简单模拟(2)

    接上一篇Linux 内核 链表 的简单模拟(1) 第五章:Linux内核链表的遍历 /** * list_for_each - iterate over a list * @pos: the & ...

  8. Linux 内核 链表 的简单模拟(1)

    第零章:扯扯淡 出一个有意思的题目:用一个宏定义FIND求一个结构体struct里某个变量相对struc的编移量,如 struct student { int a; //FIND(struct stu ...

  9. linux内核链表的移植与使用

    一.  Linux内核链表为双向循环链表,和数据结构中所学链表类似,具体不再细讲.由于在内核中所实现的函数十分经典,所以移植出来方便后期应用程序中的使用. /********************* ...

随机推荐

  1. CC协议是怎么一回事?

    CC协议是怎样的? CC-BY-NC-SA (创作共用许可协议) "知识共享"(CC协议)简单介绍 如何使用CC协议? CC 协议使用 FAQ CC协议选择工具 本文章采用 CC ...

  2. 年轻的樵夫哟,你掉的是这个免费 8 核 4G 公网服务器,还是这个随时可用的 Docker 实验平台?

    小孩子才做选择,成年人全都要.那么我们现在就来看看如何获得一台免费的 8 核 4G 公网 Docker 实验平台服务器. Play With Docker 直接打开 https://labs.play ...

  3. [Hei-Ocelot-Gateway ].Net Core Api网关Ocelot的开箱即用版本

    写在前面 很多neter都有在用Ocelot做Api网关,但是Ocelot又不像kong或者其他网关一样,开箱即用.它需要你单独开一个web项目来部署,这样很多同学都在做重复的事了. 这里[Hei.O ...

  4. 《从缺陷中学习CC++》总结

    从缺陷中学习CC++总结 从本质上来说,这就是一个CC++的错题集.全书中包括63个问题引发的错误,即书名中的缺陷.共分为10章,每一张还有一个比较经典的小结,个人感觉这本书只需要仔细看一下每一章后面 ...

  5. Spring Cloud Admin健康检查 邮件、钉钉群通知

    源码地址:https://github.com/muxiaonong/Spring-Cloud/tree/master/cloudadmin Admin 简介 官方文档:What is Spring ...

  6. 从《三体》到“中美科技战”,3分钟理解“网络”D丝为什么要迎娶“算力”白富美

    摘要:在多维的世界里,高维的文明对于低维文明具有碾压的优势,而网络也正在从二维走向三维!网络硬件的竞争主要是“芯片+算法”. 从三体到中美科技战,理解网络与算力深度融合助力高维度竞争 1:对抗封锁,需 ...

  7. zero:seo优化的三部曲

    http://www.wocaoseo.com/thread-230-1-1.html 理解用户的需求.了解搜索引擎的原理.明白如何通过搜索引擎优化对网站产生价值,这是SEO学习中应该陆续深入的三个部 ...

  8. PHP - 附件下载

    <?php $file_name = "textuse.zip";//下载文件名 $file_dir = "E:/www/xiazaiwenjian/"; ...

  9. 程序员软件开发最好的IDE集成工具eclipse各个版本的详细介绍。详细介绍,送给初学者的朋友

    对于刚接触软件开发的初学者,在下载eclipse时,对官网上面提供的各种版本的选择犹豫不决.下面将对常用的几个版本进行介绍. Eclipse版本 Eclipse Standard 该版本是eclips ...

  10. Android 设备指纹

    Android唯一识别号(设备指纹)的生成及原理 https://blog.csdn.net/xiechengfa/article/details/70049409?utm_source=itdada ...