深入分析Linux内核链表
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内核链表的更多相关文章
- 深入分析 Linux 内核链表--转
引用地址:http://www.ibm.com/developerworks/cn/linux/kernel/l-chain/index.html 一. 链表数据结构简介 链表是一种常用的组织有序数据 ...
- 深入分析 Linux 内核链表
转载:http://www.ibm.com/developerworks/cn/linux/kernel/l-chain/ 一. 链表数据结构简介 链表是一种常用的组织有序数据的数据结构,它通过指 ...
- Linux 内核链表的使用及深入分析【转】
转自:http://blog.csdn.net/BoArmy/article/details/8652776 1.内核链表和普通链表的区别 内核链表是一个双向链表,但是与普通的双向链表又有所区别.内核 ...
- C语言 Linux内核链表(企业级链表)
//Linux内核链表(企业级链表) #define _CRT_SECURE_NO_WARNINGS #include<stdio.h> #include<stdlib.h> ...
- Linux 内核链表
一 . Linux内核链表 1 . 内核链表函数 1.INIT_LIST_HEAD:创建链表 2.list_add:在链表头插入节点 3.list_add_tail:在链表尾插入节点 4.list_d ...
- linux内核链表分析
一.常用的链表和内核链表的区别 1.1 常规链表结构 通常链表数据结构至少应包含两个域:数据域和指针域,数据域用于存储数据,指针域用于建立与下一个节点的联系.按照指针域的组织以及各个节 ...
- Linux 内核 链表 的简单模拟(2)
接上一篇Linux 内核 链表 的简单模拟(1) 第五章:Linux内核链表的遍历 /** * list_for_each - iterate over a list * @pos: the & ...
- Linux 内核 链表 的简单模拟(1)
第零章:扯扯淡 出一个有意思的题目:用一个宏定义FIND求一个结构体struct里某个变量相对struc的编移量,如 struct student { int a; //FIND(struct stu ...
- linux内核链表的移植与使用
一. Linux内核链表为双向循环链表,和数据结构中所学链表类似,具体不再细讲.由于在内核中所实现的函数十分经典,所以移植出来方便后期应用程序中的使用. /********************* ...
随机推荐
- 怎么对比两个excel文档的数据差异
百度经验: https://jingyan.baidu.com/article/6181c3e0877c7a152ef15304.html
- 下面POM插件的作用是转换包名,修改tomcat跳转端口
<plugin> <groupId>org.apache.tomcat.maven</groupId> <artifactId>tomcat6-mave ...
- 【Spring注解驱动开发】如何实现方法、构造器位置的自动装配?我这样回答让面试官很满意!
在 冰河技术 微信公众号前面的文章中,我们介绍了如何使用注解来自动装配Spring组件.之前将的都是在来的字段上添加注解,那有没有什么方法可以实现方法.构造器位置的自动装配吗?今天我们就一起来探讨下如 ...
- Linux系统中有趣的命令(可以玩小游戏)
Linux系统中有趣的命令(可以玩小游戏) 前言 最近,我在看一些关于Linux系统的内容,这里面的内容是真的越学越枯燥,果然学习的过程还是不容易的.记得前几个月初学Linux时,有时候就会碰到小彩蛋 ...
- 汇编in和out实例解析
直接看例子: IN AL,21H 从21H端口读取一字节数据到AL IN AX,21H 从端口地址21H读取1字节数据到AL,从端口地址22H读取1字节到AH MOV DX,379HIN AL,DX ...
- 一文说通Jwt、Session、Cooike区别
JWT 全称是 JSON Web Token,是目前非常流行的跨域认证解决方案,在单点登录场景中经常使用到. 有些人觉得它非常好用,用了它之后就不用在服务端借助 redis 实现认证过程了,但是,还有 ...
- latex:公式中的文字
公式环境中的说明文字应置于\mbox命令中.如果已经调用了数学工具宏包或者公式宏包,可改为选用一下3条功能更强的文本命令将简短文字插入公式中. \intertext{文本} 由amsmath宏包提供, ...
- Java多线程_ThreadLocal
用法:ThreadLocal用于保存某个线程共享变量:对于同一个static ThreadLocal,不同线程只能从中get,set,remove自己的变量,而不会影响其他线程的变量. ThreadL ...
- Linux基本命令及编程环境实验
目录 一.Linux基本命令详细汇总 1.目录及文件相关命令 2.系统信息查询 3.文件操作(统计.过滤.搜索.权限) 4.其他命令 二.Linux终端上vi命令编程 1.进入vi命令模式 2.vi编 ...
- 【Spring】使用@Profile注解实现开发、测试和生产环境的配置和切换,看完这篇我彻底会了!!
写在前面 在实际的企业开发环境中,往往都会将环境分为:开发环境.测试环境和生产环境,而每个环境基本上都是互相隔离的,也就是说,开发环境.测试环境和生产环境是互不相通的.在以前的开发过程中,如果开发人员 ...