list_entry定义

/**
* list_entry - get the struct for this entry
* @ptr: the &struct list_head pointer.
* @type: the type of the struct this is embedded in.
* @member: the name of the list_struct within the struct.
*/
#define list_entry(ptr, type, member) /
((type *)((char *)(ptr)-(unsigned long)(&((type *))->member)))

  在Linux内核中,函数list_entry()用来获取节点地址.

  其不难理解为:从一个结构的成员指针找到其容器的指针。

  1. ptr是找容器的那个变量的指针,把它减去自己在容器中的偏移量的值就应该 得到容器的指针。(容器就是包含自己的那个结构)。
  2. 指针的加减要注意类型,用(char*)ptr是为了计算字节偏移。
  3. ((type *)0)->member是一个小技巧。
  4. 前面的(type *)再转回容器的类型。
#define list_entry(ptr, type, member) /
((type *)((char *)(ptr)-(unsigned long)(&((type *))->member))
  • ptr是指向list_head类型链表的指针
  • type为一个结构
  • 而member为结构type中的一个域,类型为list_head
  • 这个宏返回指向type结构的指针

  在内核代码中大量引用了这个宏,因此,搞清楚这个宏的含义和用法非常重要。

设有如下结构体定义:

typedef struct xxx
{
……(结构体中其他域,令其总大小为size1)
type1 member;
……(结构体中其他域)
}type;

定义变量:

type a;
type * b;
type1 * ptr;

执行:

ptr=&(a.member);
b=list_entry(ptr,type,member);

  这样就使b指向a,得到了a的地址。

如何做到的呢?

&((type *))->member

  把“0”强制转化为指针类型,则该指针一定指向“0”(数据段基址)。

  因为指针是“type *”型的,所以可取到以“0”为基地址的一个type型变量member域的地址。

  那么这个地址也就等于member域到结构体基地址的偏移字节数。

 ((type *)((char *)(ptr)-(unsigned long)(&((type *))->member)))

  (char *)(ptr)使得指针的加减操作步长为一字节,(unsigned long)(&((type *)0)->member)等于ptr指向的member到该member所在结构体基地址的偏移字节数。二者一减便得出该结构体的地址。转换为 (type *)型的指针,便大功告成。


list.h注释

  每一个熟悉内核的程序员,写出来的程序会更加优美和高效,因为内核代码本身就是优美和高效的,我们可以加以借荐;

  但是内核的庞大程度与复杂的各种结构使很多人望而生畏,因此我把经常使用的内核链表核心文件给加了注释,以方便使用。

 //################  注释:By 成鹏致远     ################//
//################ net :infodown.tap.cn ################//
//################ time:2013-7-30   ################// #ifndef __DLIST_H
#define __DLIST_H /* This file is from Linux Kernel (include/linux/list.h) //————————>位置
* and modified by simply removing hardware prefetching of list items. //————————>在预处理阶段对链表项进行替换
* Here by copyright, credits attributed to wherever they belong.
* Kulesh Shanmugasundaram (kulesh [squiggly] isis.poly.edu)
*/ /*
* Simple doubly linked list implementation. //————————>简单的双向链表实现
*
* Some of the internal functions (“__xxx”) are useful when
* manipulating whole lists rather than single entries, as //————————>最好对整个链表进行操作
* sometimes we already know the next/prev entries and we can
* generate better code by using them directly rather than
* using the generic single-entry routines.
*/ //################ 通过内部结构指针返回外部容器指针 ################//
/**
* container_of - cast a member of a structure out to the containing structure //————————>container_of:从一个结构的成员指针找到其容器的指针
*
* @ptr: the pointer to the member. //————————>ptr:指向menber的指针,即找容器的那个变量的指针
* @type: the type of the container struct this is embedded in. //————————>type:容器的类型
* @member: the name of the member within the struct. //————————>member:容器中struct类型成员
*
*/
#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER) //————————>offsetof:TYPE结构类型中MEMBER结构指针与TYPE结构指针的偏移量 #define container_of(ptr, type, member) ({ \ //————————>container_of:从一个结构的成员指针找到其容器的指针
const typeof( ((type *))->member ) *__mptr = (ptr); \ //————————>ptr:指向menber的指针,即找容器的那个变量的指针
(type *)( (char *)__mptr - offsetof(type,member) );}) //————————>type:容器的类型
//————————>member:容器中struct类型成员 //################ 链表初始化 ################//
/*
* These are non-NULL pointers that will result in page faults //————————>野指针会导致页面出错
* under normal circumstances, used to verify that nobody uses //————————>以下初始化方法保证了不会出现野指针(确认没有空指针传入)
* non-initialized list entries.
*/
#define LIST_POISON1 ((void *) 0x00100100)
#define LIST_POISON2 ((void *) 0x00200 struct list_head { //————————>内核链表结构
struct list_head *next, *prev;
}; #define LIST_HEAD_INIT(name) { &(name), &(name) } //————————>LIST_HEAD_INIT(name):用name来初始化链表 #define LIST_HEAD(name) \ //————————>LIST_HEAD(name):间接用LIST_HEAD_INIT(name)来初始化链表,本质:LIST_HEAD(name)用来定义+初始化
struct list_head name = LIST_HEAD_INIT(name) #define INIT_LIST_HEAD(ptr) do { \ //————————>运行时初始化,功能相同:初始化
(ptr)->next = (ptr); (ptr)->prev = (ptr); \
} while () //################ 链表插入算法 ################//
/*
* Insert a new entry between two known consecutive entries. //————————>在两个连续的结点间插入新的结点
*
* This is only for internal list manipulation where we know //————————>只能用于操作已知prev和next指针的内部链表
* the prev/next entries already!
*/
static inline void __list_add(struct list_head *new, //————————>__list_add:内联静态函数
struct list_head *prev, //————————>参数:三个指向list_head的结构体指针(新结点,前向结点,后向结点)
struct list_head *next)
{
next->prev = new; //————————>双向链表中插入new结点
new->next = next;
new->prev = prev;
prev->next = new;
} /**
* list_add – add a new entry //————————>list_add:头插法增加新节点
* @new: new entry to be added //————————>new:新节点指针
* @head: list head to add it after //————————>head:链表头结点指针,在之后插入
*
* 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:在head后面插入new
{ //————————>new:新节点指针
__list_add(new, head, head->next); //————————>head:链表头结点指针
} /**
* list_add_tail – add a new entry //————————>list_add_tail :尾插法增加新节点
* @new: new entry to be added //————————>new:新节点指针
* @head: list head to add it beforer //————————>head:链表头结点指针,在之前插入
*
* 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_tail :在head前面插入new
{
__list_add(new, head->prev, head);
} //################ 链表删除算法 ################//
/*
* Delete a list entry by making the prev/next entries //————————>通过改变prev和next的指向来删除节点
* point to each other.
*
* This is only for internal list manipulation where we know //————————>同样只能用于操作已知prev和next指针的内部链表
* the prev/next entries already!
*/
static inline void __list_del(struct list_head *prev, struct list_head *next) //————————>__list_del:删除结点
{ //————————>prev:待删除结点的前向指针
next->prev = prev; //————————>next:待删除结点的后向指针
prev->next = next;
} /**
* list_del – deletes entry from list. //————————>list_del:删除节点
* @entry: the element to delete from the list. //————————>entry:要删除的结点
* Note: list_empty on entry does not return true after this, the entry is in an undefined state. //————————>操作后调用list_empty则返回随机值
*/
static inline void list_del(struct list_head *entry) //————————>删除entry结点
{
__list_del(entry->prev, entry->next);
entry->next = (void *) ; //————————>置空
entry->prev = (void *) ;
} /**
* list_del_init – deletes entry from list and reinitialize it. //————————>list_del_init:删除并初始化节点
* @entry: the element to delete from the list.
*/
static inline void list_del_init(struct list_head *entry) //————————>删除并初始化entry指向的结点
{
__list_del(entry->prev, entry->next); //————————>删除
INIT_LIST_HEAD(entry); //————————>然后初始化
} //################ 链表移动算法 ################//
/**
* list_move – delete from one list and add as another’s head //————————>list_move:从链表中删除一个节点并添加到另一个链表头部
* @list: the entry to move //————————>list:要移动的节点
* @head: the head that will precede our entry //————————>head:目标链表的头结点
*/
static inline void list_move(struct list_head *list, //————————>list_move:从链表中删除list并添加到head后面
struct list_head *head)
{
__list_del(list->prev, list->next); //————————>先删除
list_add(list, head); //————————>然后在head后面添加list
} /**
* list_move_tail – delete from one list and add as another’s tail //————————>list_move_tail:从链表中删除一个节点并添加到另一个链表尾部
* @list: the entry to move
* @head: the head that will follow our entry
*/
static inline void list_move_tail(struct list_head *list, //————————>list_move_tail:从链表中删除list并添加到head前部
struct list_head *head)
{
__list_del(list->prev, list->next); //————————>先删除
list_add_tail(list, head); //————————>然后在head前面添加list
} //################ 判断链表空状态 ################//
/**
* list_empty – tests whether a list is empty
* @head: the list to test.
*/
static inline int list_empty(struct list_head *head) //————————>list_empty:判断head指向的链表是否为空
{
return head->next == head; //————————>只有一个头结点
} //################ 链表合并算法 ################// static inline void __list_splice(struct list_head *list, //————————>__list_splice:将list链表合并到head链表上
struct list_head *head)
{
struct list_head *first = list->next; //————————>list的首结点
struct list_head *last = list->prev; //————————>list的尾结点
struct list_head *at = head->next; //————————>head的首结点
//————————>将list所以结点链接到head的后面
first->prev = head; //————————>list首结点向前指向head
head->next = first; //————————>head向后指向list的首结点 last->next = at; //————————>list的尾结点向后指向head的首结点
at->prev = last; //————————>head的首结点向前指向list的尾结点
} /**
* list_splice – join two lists //————————>list_splice:合并两个链表
* @list: the new list to add. //————————>list:要合并的链表
* @head: the place to add it in the first list. //————————>目标链表
*/
static inline void list_splice(struct list_head *list, struct list_head *head) //————————>list_splice:将list合并到head后面
{
if (!list_empty(list)) //————————>条件:list链表不为空
__list_splice(list, head);
} /**
* list_splice_init – join two lists and reinitialise the emptied list. //————————>list_splice_init:合并两个链表并重新初始化被链接的链表2013-7-30
* @list: the new list to add. //————————>list:要合并的链表
* @head: the place to add it in the first list. //————————>目标链表
*
* The list at @list is reinitialised //————————>list:被重新初始化
*/
static inline void list_splice_init(struct list_head *list, //————————>list_splice_init:将list合并到head,并重新初始化list
struct list_head *head)
{
if (!list_empty(list)) { //————————>条件:list链表不为空
__list_splice(list, head);
INIT_LIST_HEAD(list);
}
} //################ 通过内部结构指针返回外部容器指针 ################//
/**
* list_entry – get the struct for this entry //————————>list_entry:得到结点的外部结构地址
* @ptr: the &struct list_head pointer. //————————>ptr:指向struct list_head类型链表的指针
* @type: the type of the struct this is embedded in. //————————>type:包含结点的结构体类型
* @member: the name of the list_struct within the struct. //————————>member:type结构中的结点类型
*/
#define list_entry(ptr, type, member) \ //————————>list_entry:得到type结构的指针
((type *)((char *)(ptr)-(unsigned long)(&((type *))->member))) //————————>ptr:指向struct list_head类型链表的指针
//————————>type:包含结点的结构体类型
//————————>member:type结构中的结点类型 //################ 链表遍历算法 ################//
/**
* list_for_each - iterate over a list //————————>list_for_each:迭代一个链表
* @pos: the &struct list_head to use as a loop counter. //————————>pos:循环计数器,struct list_head类型
* @head: the head for your list. //————————>遍历链表头指针
*/
#define list_for_each(pos, head) \ //————————>list_for_each:利用for循环迭代head指向的链表
for (pos = (head)->next; pos != (head); \
pos = pos->next) //————————>通过next指针逐项后移 /**
* list_for_each_prev - iterate over a list backwards //————————>list_for_each_prev:反向迭代一个链表
* @pos: the &struct list_head to use as a loop counter. //————————>pos:循环计数器,struct list_head类型
* @head: the head for your list. //————————>遍历链表头指针
*/
#define list_for_each_prev(pos, head) \ //————————>list_for_each_prev:利用for循环反向迭代head指向的链表
for (pos = (head)->prev; pos != (head); \
pos = pos->prev) //————————>也是通过next指针逐项后移 /**
* list_for_each_safe - iterate over a list safe against removal of list entry //————————>list_for_each_safe:迭代一个链表
* @pos: the &struct list_head to use as a loop counter.
* @n: another &struct list_head to use as temporary storage //————————>多用一个临时辅助变量进行迭代
* @head: the head for your list.
*/
#define list_for_each_safe(pos, n, head) \
for (pos = (head)->next, n = pos->next; pos != (head); \
pos = n, n = pos->next) /**
* list_for_each_entry - iterate over list of given type //————————>list_for_each_entry:遍历链表中的内核链表容器结构
* @pos: the type * to use as a loop counter. //————————>数据项结构指针类型,指向外部结构体
* @head: the head for your list. //————————>遍历链表头指针
* @member: the name of the list_struct within the struct. //————————>链表中结构成员的名字
*/
#define list_for_each_entry(pos, head, member) \ //————————>list_for_each_entry:遍历head指向的链表的容器结构(外部结构体)
for (pos = list_entry((head)->next, typeof(*pos), member); \
&pos->member != (head); \
pos = list_entry(pos->member.next, typeof(*pos), member)) //————————>通过list_entry传入next来遍历外部结构 /**
* list_for_each_entry_safe – iterate over list of given type safe against removal of list entry //————————>llist_for_each_entry_safe:遍历链表中的内核链表容器结构
* @pos: the type * to use as a loop counter.
* @n: another type * to use as temporary storage //————————>多用一个临时辅助变量进行迭代
* @head: the head for your list.
* @member: the name of the list_struct within the struct.
*/
#define list_for_each_entry_safe(pos, n, head, member) \ //————————>list_for_each_entry_safe:遍历head指向的链表的容器结构(外部结构体)
for (pos = list_entry((head)->next, typeof(*pos), member), \
n = list_entry(pos->member.next, typeof(*pos), member); \
&pos->member != (head); \
pos = n, n = list_entry(n->member.next, typeof(*n), member)) #endif

【内核】内核链表使用说明,list.h注释的更多相关文章

  1. linux内核中链表代码分析---list.h头文件分析(一)【转】

    转自:http://blog.chinaunix.net/uid-30254565-id-5637596.html linux内核中链表代码分析---list.h头文件分析(一) 16年2月27日17 ...

  2. linux内核中链表代码分析---list.h头文件分析(二)【转】

    转自:http://blog.chinaunix.net/uid-30254565-id-5637598.html linux内核中链表代码分析---list.h头文件分析(二) 16年2月28日16 ...

  3. Linux内核【链表】整理笔记(1)

    我们都知道Linux内核里的双向链表和学校里教给我们的那种数据结构还是些不一样.Linux采用了一种更通用的设计,将链表以及其相关操作函数从数据本身进行剥离,这样我们在使用链表的时候就不用自己去实现诸 ...

  4. linux 内核的链表操作(好文不得不转)

    以下全部来自于http://www.ibm.com/developerworks/cn/linux/kernel/l-chain/index.html 无任何个人意见. 本文详细分析了 2.6.x 内 ...

  5. Linux嵌入式 -- 内核 - 内核链表

    1. linux内核链表 链表数据结构的定义: struct list_head  {  struct list_head *next, *prev;  };  list_head结构包含两个指向li ...

  6. 鸿蒙内核源码分析(源码注释篇) | 鸿蒙必定成功,也必然成功 | 百篇博客分析OpenHarmony源码 | v13.02

    百篇博客系列篇.本篇为: v13.xx 鸿蒙内核源码分析(源码注释篇) | 鸿蒙必定成功,也必然成功 | 51.c.h .o 几点说明 kernel_liteos_a_note | 中文注解鸿蒙内核 ...

  7. Linux内核单链表

    主要说明Linux内核中单链表操作的关键思想,需要注意的地方 1. 假设 为了说明关键思想,对数据结构进行了精简 2. 数据结构定义 struct ListNode { int val; ListNo ...

  8. 24小时学通Linux内核--内核探索工具类

    寒假闲下来了,可以尽情的做自己喜欢的事情,专心待在实验室里燥起来了,因为大二的时候接触过Linux,只是关于内核方面确实是不好懂,所以十天的时间里还是希望能够补充一下Linux内核相关知识,接下来继续 ...

  9. Linux内核-内核线程

    线程分类:内核线程.用户线程(指不需要内核支持而完全建立在用户空间的线程库,这种线程效率高,由于Linux内核没有轻量级进程(线程)的概念,因此不能独立的对用户线程进行调度,而是由一个线程运行库来组织 ...

随机推荐

  1. linux nginx配置新项目加域名(设置绑定域名)

    转自:linux nginx配置新项目加域名 找到nginx的配置文件 nginx/nginx.conf 第一种方,法直接在nginx.com里面配置 user www www; worker_pro ...

  2. maven Missing artifact com.sun:tools:jar:1.5.0

    转自:http://blog.csdn.net/caolaosanahnu/article/details/7918929 http://zuoshahao.com/work/others/missi ...

  3. Android tesseract-orc之扫描身份证号码

    踩了不少坑,终于把这个扫描版的身份证识别做出来了,图片识别引擎用的是tesseract,在已经训练好样本的情况下,感觉识别率还是一般般~ 下面说一说大概几个坑. 一. 编译tesseract-orc ...

  4. 安装Tomcat的Apr

    转:http://www.cnblogs.com/littlehb/archive/2013/04/02/2994785.html 安装Tomcat的Apr,提升性能 发现 Tomcat 可以用 Ap ...

  5. android异步处理机制

    昨天面试被提问android的异步处理机制有哪些,他说处理new thread还有哪种方式,我说implement runnable,他说不是,比如intentservice. 我说那还有asyncT ...

  6. Postman 网络调试工具

    1.Postman 简介 Postman 是一款功能强大的网页调试与发送网页 HTTP 请求的工具.我们可以用来很方便的模拟 get 或者 post 或者其他方式的请求来调试接口. 官网下载地址 Po ...

  7. 关于varchar(max), nvarchar(max)和varbinary(max)

    在MS SQL2005及以上的版本中,加入大值数据类型(varchar(max).nvarchar(max).varbinary(max) ).大值数据类型最多可以存储2^30-1个字节的数据.这几个 ...

  8. 使用Unified Auditing Policy审计数据泵导出操作

    1.创建审计策略 SQL> alter session set container=pdb1; SQL> create or replace directory dumpdir as '/ ...

  9. android:fitsSystemWindows属性的用法

    属性说明 fitsSystemWindows属性可以让view根据系统窗口来调整自己的布局:简单点说就是我们在设置应用布局时是否考虑系统窗口布局,这里系统窗口包括系统状态栏.导航栏.输入法等,包括一些 ...

  10. appium简明教程(2)——appium的基本概念

    Client/Server Architecture appium的核心其实是一个暴露了一系列REST API的server. 这个server的功能其实很简单:监听一个端口,然后接收由client发 ...