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. Ng-Matero V10 正式发布!

    Angular v10 在六月下旬就悄无声息的发布了,虽然 v9 的发布延期了两个月,但是 v10 并没有受影响,仍然如期而至. 相比 v9 的重量级发布,v10 并没有颠覆性的变化,主要还是 bug ...

  2. 兼容ie9上传本地资源

    在ie9中上传文件出现问题,大多数的上传文件都采用new Formdata创建添加文件,在IE9中不支持Formdata对象操作,ie10是支持的.所以只能使用表单提交的方式进行操作. <for ...

  3. phpstudy后门利用复现

    一.漏洞位置 程序自带的PHP的php_xmlrpc.dll模块中有隐藏后门,受影响的版本有phpstudy2016(php5.2/5.4).phpstudy2018(php5.2/5.4)等版本. ...

  4. Java不可重入锁和可重入锁的简单理解

    基础知识 Java多线程的wait()方法和notify()方法 这两个方法是成对出现和使用的,要执行这两个方法,有一个前提就是,当前线程必须获其对象的monitor(俗称“锁”),否则会抛出Ille ...

  5. Jmeter 常用函数(13)- 详解 __machineIP

    如果你想查看更多 Jmeter 常用函数可以在这篇文章找找哦 https://www.cnblogs.com/poloyy/p/13291704.html 作用 返回机器(电脑)IP 语法格式 ${_ ...

  6. openstack nova 创建虚机流程

    1文件 nova.api.openstack.coumpute.servers1函数 def create(self, req, body):1调用 (instances, resv_id) = se ...

  7. latex三种标准文类book, report, article的章节命令与层次深度

    Latex有三种标准文类:book, report, article. 每种文类的章节命令和层次深度如下: 三种标准文类的章节命令与层次深度 层次深度 层次名 book report article ...

  8. linux计算命令

    1.在lammps中通过car文件导出data文件 (进入工作目录xxx cd xxx/ msi2lmp.exe xxx -class I -frc clayff -i -ignore > ou ...

  9. xmind8 破解激活教程

    这里以windows为例来演示,其它操作系统需根据情况修改相应步骤. 一.下载安装包 首先去xmind国外官网下载对应操作系统的安装包,国内官网的那个是有残缺的,不支持破解. 官网下载链接 二.下载破 ...

  10. jdk8的下载、安装、配置

    jdk官方网址:https://www.oracle.com/java/technologies/javase-downloads.html 小编微信和公众号(很高兴能与各位交流学习) 以下是具体步骤 ...