list_head的核心源代码都在<linux/list.h>文件中,该文件包含了主要的inline函数和宏.
下面的代码是一些关键函数和宏的分析.
struct list_head结构体:
struct list_head {
struct list_head *next, *prev;
};
LIST_HEAD_INIT宏:
#define LIST_HEAD_INIT(name) { &(name), &(name) }
LIST_HEAD宏:
#define LIST_HEAD(name) \
struct list_head name = LIST_HEAD_INIT(name)
LIST_HEAD(list)宏展开后相当于
struct list_head list = { &list, &list}
用于定义一个纯粹的list_head节点
+-> +----------+ <-+
+---| prev | |
+----------+ |
| next |---+
+----------+
list
list_add函数:
/**
* list_add - 添加新链表项
* @new: 要添加的新项
* @head: 将新项添加到head之后
*
* 将新表项插入到指定的head之后.
* 使用它实现Stack是非常有用的.
*/
static inline void list_add(struct list_head *new, struct list_head *head)
{
__list_add(new, head, head->next);
}
list_add_tail函数:
/**
* list_add_tail - 添加新链表项
* @new: 要添加的新项
* @head: 将新表项添加到head之后
*
* 将新表项插入到指定的head之前.
* 使用它实现Queue是非常有用的.
*/
static inline void list_add_tail(struct list_head *new, struct list_head *head)
{
__list_add(new, head->prev, head);
}
__list_add函数:
/**
* 在两个连续的链表项之间加入一个新项
*
* 这个函数仅于链表内部处理,且prev和next链表项的已知的.
*/
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;
}
+-----------+ +------------+ +------------+
| prev |<-------| prev |<------| prev |
+-----------+ +------------+ +------------+
| next |------->| next |------>| next |
+-----------+ +------------+ +------------+
prev new next
list_del函数:
/**
* list_del - 从链表中删除项
* @entry: 被删除的元素
* 注意: 在此函数之后,在entry上调用list_empty()不会返回true, entry处于未知状态
*/
static inline void list_del(struct list_head *entry)
{
__list_del(entry->prev, entry->next);
entry->next = LIST_POISON1;//LIST_POISON1表示一种未知的指针
etnry->prev = LIST_POISON2;//LIST_POISON2同上
}
LIST_POISON1和LIST_POISON2定义在<linux/poison.h>文件中:
#define LIST_POISON1 ((void *) 0x00100100 + POISON_POINTER_DELTA)
#define LIST_POISON2 ((void *) 0x00200200 + POISON_POINTER_DELTA)
list_del_init函数:
/**
* list_del_init - 从链表中删除项,并重新初始化这个项
* @entry: 从链表中删除的元素
*/
static inline void list_del_init(struct list_head *entry)
{
__list_del(entry->prev, entry->next);
INIT_LIST_HEAD(entry);
}
INIT_LIST_HEAD函数:
/**
* INIT_LIST_HEAD - 将list的prev和next指向自身
*/
static inline void INIT_LIST_HEAD(struct list_head *list)
{
list->next = list;
list->prev = list;
}
__list_del函数:
/**
* 通过使prev/next指针指向彼此来删除一个链表项
*
* 这个仅用于链表内部处理,且prev/next项都是已知的.
*/
static inline void __list_del(struct list_head *prev, struct list_head *next)
{
next->prev = prev;
prev->next = next;
}
list_replace函数:
/**
* list_replace - 用新节点替换旧节点
* @old: 被替换的旧元素
* @new: 新元素
*/
static inline void list_replace(struct list_head *old,
struct list_head *new)
{
new->next = old->next;
new->next->prev = new;/*将old->next节点指向new*/
new->prev = old->prev;
new->prev->next = new;/*将old->prev节点指向new*/
}
list_move函数:
/**
* list_move - 将一个表中的项移到另一个表头
* @list: 移动的链表项
* @head: 链表头
*/
static inline void list_move(struct list_head *list, struct list_head *head)
{
__list_del(list->prev, list->next);/*从表中删除*/
list_add(list, head);/*添加到表头*/
}
list_empty函数:
/**
* list_empty - 测试链表是否为空
* @head: 测试链表表头
*/
static inline int list_empty(const struct list_head *head)
{
return head->next == head;
}
list_is_last函数:
/**
* list_is_last - 测试list是否为head表的尾节点
* @list: 测试节点
* @head: 测试链表表头
*/
static inline int list_is_last(const struct list_head *list,
const struct list_head *head)
{
return list->next == head;
}
list_rotate_left函数:
/**
* list_rotate_left - 将链表元素循环左移
* @head: 链表表头
*/
static inline void list_rotate_left(struct list_head *head)
{
struct list_head *first;
if (!list_empty(head)) {
first = head->next;
list_move_tail(first, head);/*将第一个元素移动尾部*/
}
}
list_splice函数:
/**
* list_splice - 连接两个链表, 它为Stack而设计
* @list: 要添加的的新链表
* @head: 将第一个list添加到head之后
*/
static inline void list_splice(const struct list_head *list,
struct list_head *head)
{
if (!list_empty(list))
__list_splice(list, head, head->next);
}
list_splice_tail函数:
/**
* list_splice_tail - 连接两个链表, 它为Queue设计
*/
static inline void list_splice_tail(struct list_head *list,
struct list_head *head)
{
if (!list_empty(list))
__list_splice(list, head->prev, head);
}
__list_splice函数:
/**
* __list_splice - 将list拼接到prev和next链表项之间
*
* 注意: 拼接时不包含list表头
*/
static inline void __list_splice(const struct list_head *list,
struct list_head *prev,
struct list_head *next)
{
struct list_head *first = list->next;
struct list_head *last = list->prev;
first->prev = prev;
prev->next = first;
last->next = next;
next->prev = last;
}
list_entry宏:
/**
* list_entry - 获取包含此链表项的结构体
* @ptr: 指向结构体内的list_head成员的指针
* @type: 嵌入此链表项的结构体类型
* @member: list_head在结构体中的名称
*/
#define list_entry(ptr, type, member) \
container_of(ptr, type, member)
container_of宏:
该宏定义在<linux/kernel.h>中
#define container_of(ptr, type, member) ({ \
const typeof( ((type *)0)->member ) *__mptr = (ptr); \
(type *)( (char *)__mptr - offsetof(type, member) );})
typeof(x)获取x数据类型
offsetof(type, memeber)获取member在type中的偏移量
结构体的地址 = 某成员地址 - 该成员在结构体中的偏移量
+-----------+<----- mptr - offsetof(type, member)
| | |
| ... | |offsetof(type, member)
| | |
+-----------+<----- mptr
| member |
+-----------+
| ... |
+-----------+
list_for_each宏:
/**
* list_for_each - 遍历一个链表
* @pos: 循环游标,指向每次遍历的节点
* @head: 链表的头节点
*/
#define list_for_each(pos, head) \
for (pos = (head)->next; prefetch(pos->next), pos != (head); \
pos = pos->next)
prefech试图将pos->next存放到CPU L1缓存中,有利于下次快速获取.
下面的代码是一些关键函数和宏的分析.
struct list_head结构体:
struct list_head {
struct list_head *next, *prev;
};
LIST_HEAD_INIT宏:
#define LIST_HEAD_INIT(name) { &(name), &(name) }
LIST_HEAD宏:
#define LIST_HEAD(name) \
struct list_head name = LIST_HEAD_INIT(name)
LIST_HEAD(list)宏展开后相当于
struct list_head list = { &list, &list}
用于定义一个纯粹的list_head节点
+-> +----------+ <-+
+---| prev | |
+----------+ |
| next |---+
+----------+
list
list_add函数:
/**
* list_add - 添加新链表项
* @new: 要添加的新项
* @head: 将新项添加到head之后
*
* 将新表项插入到指定的head之后.
* 使用它实现Stack是非常有用的.
*/
static inline void list_add(struct list_head *new, struct list_head *head)
{
__list_add(new, head, head->next);
}
list_add_tail函数:
/**
* list_add_tail - 添加新链表项
* @new: 要添加的新项
* @head: 将新表项添加到head之后
*
* 将新表项插入到指定的head之前.
* 使用它实现Queue是非常有用的.
*/
static inline void list_add_tail(struct list_head *new, struct list_head *head)
{
__list_add(new, head->prev, head);
}
__list_add函数:
/**
* 在两个连续的链表项之间加入一个新项
*
* 这个函数仅于链表内部处理,且prev和next链表项的已知的.
*/
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;
}
+-----------+ +------------+ +------------+
| prev |<-------| prev |<------| prev |
+-----------+ +------------+ +------------+
| next |------->| next |------>| next |
+-----------+ +------------+ +------------+
prev new next
list_del函数:
/**
* list_del - 从链表中删除项
* @entry: 被删除的元素
* 注意: 在此函数之后,在entry上调用list_empty()不会返回true, entry处于未知状态
*/
static inline void list_del(struct list_head *entry)
{
__list_del(entry->prev, entry->next);
entry->next = LIST_POISON1;//LIST_POISON1表示一种未知的指针
etnry->prev = LIST_POISON2;//LIST_POISON2同上
}
LIST_POISON1和LIST_POISON2定义在<linux/poison.h>文件中:
#define LIST_POISON1 ((void *) 0x00100100 + POISON_POINTER_DELTA)
#define LIST_POISON2 ((void *) 0x00200200 + POISON_POINTER_DELTA)
list_del_init函数:
/**
* list_del_init - 从链表中删除项,并重新初始化这个项
* @entry: 从链表中删除的元素
*/
static inline void list_del_init(struct list_head *entry)
{
__list_del(entry->prev, entry->next);
INIT_LIST_HEAD(entry);
}
INIT_LIST_HEAD函数:
/**
* INIT_LIST_HEAD - 将list的prev和next指向自身
*/
static inline void INIT_LIST_HEAD(struct list_head *list)
{
list->next = list;
list->prev = list;
}
__list_del函数:
/**
* 通过使prev/next指针指向彼此来删除一个链表项
*
* 这个仅用于链表内部处理,且prev/next项都是已知的.
*/
static inline void __list_del(struct list_head *prev, struct list_head *next)
{
next->prev = prev;
prev->next = next;
}
list_replace函数:
/**
* list_replace - 用新节点替换旧节点
* @old: 被替换的旧元素
* @new: 新元素
*/
static inline void list_replace(struct list_head *old,
struct list_head *new)
{
new->next = old->next;
new->next->prev = new;/*将old->next节点指向new*/
new->prev = old->prev;
new->prev->next = new;/*将old->prev节点指向new*/
}
list_move函数:
/**
* list_move - 将一个表中的项移到另一个表头
* @list: 移动的链表项
* @head: 链表头
*/
static inline void list_move(struct list_head *list, struct list_head *head)
{
__list_del(list->prev, list->next);/*从表中删除*/
list_add(list, head);/*添加到表头*/
}
list_empty函数:
/**
* list_empty - 测试链表是否为空
* @head: 测试链表表头
*/
static inline int list_empty(const struct list_head *head)
{
return head->next == head;
}
list_is_last函数:
/**
* list_is_last - 测试list是否为head表的尾节点
* @list: 测试节点
* @head: 测试链表表头
*/
static inline int list_is_last(const struct list_head *list,
const struct list_head *head)
{
return list->next == head;
}
list_rotate_left函数:
/**
* list_rotate_left - 将链表元素循环左移
* @head: 链表表头
*/
static inline void list_rotate_left(struct list_head *head)
{
struct list_head *first;
if (!list_empty(head)) {
first = head->next;
list_move_tail(first, head);/*将第一个元素移动尾部*/
}
}
list_splice函数:
/**
* list_splice - 连接两个链表, 它为Stack而设计
* @list: 要添加的的新链表
* @head: 将第一个list添加到head之后
*/
static inline void list_splice(const struct list_head *list,
struct list_head *head)
{
if (!list_empty(list))
__list_splice(list, head, head->next);
}
list_splice_tail函数:
/**
* list_splice_tail - 连接两个链表, 它为Queue设计
*/
static inline void list_splice_tail(struct list_head *list,
struct list_head *head)
{
if (!list_empty(list))
__list_splice(list, head->prev, head);
}
__list_splice函数:
/**
* __list_splice - 将list拼接到prev和next链表项之间
*
* 注意: 拼接时不包含list表头
*/
static inline void __list_splice(const struct list_head *list,
struct list_head *prev,
struct list_head *next)
{
struct list_head *first = list->next;
struct list_head *last = list->prev;
first->prev = prev;
prev->next = first;
last->next = next;
next->prev = last;
}
list_entry宏:
/**
* list_entry - 获取包含此链表项的结构体
* @ptr: 指向结构体内的list_head成员的指针
* @type: 嵌入此链表项的结构体类型
* @member: list_head在结构体中的名称
*/
#define list_entry(ptr, type, member) \
container_of(ptr, type, member)
container_of宏:
该宏定义在<linux/kernel.h>中
#define container_of(ptr, type, member) ({ \
const typeof( ((type *)0)->member ) *__mptr = (ptr); \
(type *)( (char *)__mptr - offsetof(type, member) );})
typeof(x)获取x数据类型
offsetof(type, memeber)获取member在type中的偏移量
结构体的地址 = 某成员地址 - 该成员在结构体中的偏移量
+-----------+<----- mptr - offsetof(type, member)
| | |
| ... | |offsetof(type, member)
| | |
+-----------+<----- mptr
| member |
+-----------+
| ... |
+-----------+
list_for_each宏:
/**
* list_for_each - 遍历一个链表
* @pos: 循环游标,指向每次遍历的节点
* @head: 链表的头节点
*/
#define list_for_each(pos, head) \
for (pos = (head)->next; prefetch(pos->next), pos != (head); \
pos = pos->next)
prefech试图将pos->next存放到CPU L1缓存中,有利于下次快速获取.