- 常规链表的缺陷
- Linux内核链表的原理
- 查看内核链表
- 构建节点
- 初始化链表
- //插入节点
- //遍历链表
传统的双向循环链表概念简单,操作方便,但存在有致命的缺陷,用一句话来概括就是:
每一条链表都是特殊的,不具有通用性。换句话说,对于每一种不同的数据,所构建出来的
传统链表都是跟这些数据相关的,所有的链表操作函数也都是数据相关的,换一种数据节点,
则所有的操作函数都需要一一重写编写,这种缺陷对于一个具有成千上万种数据节点的工程
来说是灾难性的,是不可接受的
Linux内核链表的原理(1)把传统链表中的“链”抽象出来,使之成为一条只包含前后指针的纯粹的双循环链表,这样的链表由于不含有特殊的数据,因此它实质上就是链表的抽象表示
(2)将链表寄宿与具体的数据节点之中,使他贯穿这些节点,可以借助一定的方式通过纯粹链表的指针域得到数据节点
既然 Linux 内核链表是一种统一的抽象的数据结构实现,那么在 Linux 源码中就有专门的已经写好的代码,实现了内核链表的初始化、插入、删除、遍历、移动等等,这些代码被保存在内核目录中的 inlucde/linux/list.h 中
查找 find / -name list.h
//指针域部分,小结构体,用它来构建“纯粹链表”
struct list_head
{
struct list_head *next, *prev;
};
构建节点
typedef int Datatype;
//双向循环链表节点
typedef struct Node //大结构体,结构体里面存放数据跟小结构体
{
DataType data; //数据域
struct list_head list; //小结构体,存放的是大结构体的前驱指针和后继指针
}LinkNode;
初始化链表
//节点结构体变量初始化
#define LIST_HEAD_INIT(name) { &(name), &(name) }
#define LIST_HEAD(name)
struct list_head name = LIST_HEAD_INIT(name)
//节点结构体指针初始化
#define INIT_LIST_HEAD(ptr) do {
(ptr)->next = (ptr); (ptr)->prev = (ptr);
} while (0)
//初始化空链表
LinkNode * InitLinkNode()
{
LinkNode * head = (LinkNode *)malloc(sizeof(LinkNode));
if(head!=NULL)
{
// head->list.next = head->list.prev = &(head->list);
INIT_LIST_HEAD(&(head->list));
}
return head;
}
//新建节点
LinkNode * CreateNode(DataType data)
{
LinkNode * new = (LinkNode *)malloc(sizeof(LinkNode));
if(new!=NULL)
{
new->data = data;
new->list.next = NULL;
new->list.prev = NULL;
}
return new;
}
//插入节点
//将new节点插入到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;
}
//将new节点插入到head节点后面
static inline void list_add(struct list_head *new, struct list_head *head)
{
__list_add(new, head, head->next);
}
//将new节点插入到head的前面
static inline void list_add_tail(struct list_head *new, struct list_head *head)
{
__list_add(new, head->prev, head);
}
//空链表判断
// static inline int list_empty(struct list_head *head)
// {
// return head->next == head;
// }
int InsertNodeHead(LinkNode *head,LinkNode *new)
{
if(list_empty(&(new->list))||list_empty(&(new->list)))
{
return 0;
}
list_add(&(new->list),&(head->list));
return 1;
}
int InsertNodeTail(LinkNode *head,LinkNode *new)
{
if(list_empty(&(new->list))||list_empty(&(new->list)))
{
return 0;
}
list_add_tail(&(new->list),&(head->list));
return 1;
}
//遍历链表
#define list_for_each(pos, head) //只适用遍历,不适用删除 #define list_for_each_prev(pos, head) //只适用遍历,不适用删除 #define list_for_each_safe(pos, n, head) //安全 #define list_for_each_entry(pos, head, member) //只适用遍历,不适用删除 #define list_for_each_entry_safe(pos, n, head, member) //安全
//遍历链表的for循环,每一次循环体内得到的就是一个小结构体指针
//从前往后遍历
// #define list_for_each(pos, head)
// for (pos = (head)->next; pos != (head);
// pos = pos->next)
// * 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.
// //小结构体指针ptr,大结构体类型type,小结构体在大结构体内部的成员名
// #define list_entry(ptr, type, member)
// ((type *)((char *)(ptr)-(unsigned long)(&((type *)0)->member)))
void Display1(LinkNode *head)
{
struct list_head *ptr=NULL;
LinkNode *p=NULL;
list_for_each(ptr,&(head->list))
{
p=list_entry(ptr,LinkNode,list);
printf("%d ",p->data);
}
printf("n");
}
//从后往前遍历
//#define list_for_each_prev(pos, head)
//for (pos = (head)->prev; pos != (head);
//pos = pos->prev)
void Display2(LinkNode *head)
{
struct list_head *ptr=NULL;
LinkNode *p=NULL;
list_for_each_prev(ptr,&(head->list))
{
p=list_entry(ptr,LinkNode,list);
printf("%d ",p->data);
}
printf("n");
}
// //安全的遍历,防止在循环体中有对节点的删除操作,这样会导致下一次进入循环体出现段错误
// #define list_for_each_safe(pos, n, head)
// for (pos = (head)->next, n = pos->next; pos != (head);
// pos = n, n = pos->next)
void Display3(LinkNode *head)
{
struct list_head *ptr=NULL;
struct list_head *n=NULL;
LinkNode *p=NULL;
list_for_each_safe(ptr,n,&(head->list))
{
p=list_entry(ptr,LinkNode,list);
printf("%d ",p->data);
}
printf("n");
}
//遍历过程中,得到大结构体指针:
//pos是遍历过程中的大结构体指针变量,
//head是小结构体链表头指针
//member小结构体在大结构体里面的成员名
// #define list_for_each_entry(pos, head, member)
// for (pos = list_entry((head)->next, typeof(*pos), member);
// &pos->member != (head);
// pos = list_entry(pos->member.next, typeof(*pos), member))
void Display4(LinkNode *head)
{
LinkNode *ptr=NULL;
list_for_each_entry(ptr,&(head->list),list)
{
printf("%d ",ptr->data);
}
printf("n");
}
// #define list_for_each_entry_safe(pos, n, head, member)
// 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))
void Display5(LinkNode *head)
{
LinkNode *ptr=NULL;
LinkNode *n=NULL;
list_for_each_entry_safe(ptr,n,&(head->list),list)
{
printf("%d ",ptr->data);
}
printf("n");
}
#include#include #include #include "list.h" typedef int DataType; //双向循环链表节点 typedef struct Node //大结构体,结构体里面存放数据跟小结构体 { DataType data; //数据域 struct list_head list; //小结构体,存放的是大结构体的前驱指针和后继指针 }LinkNode; // //节点结构体指针初始化 // #define INIT_LIST_HEAD(ptr) do { // (ptr)->next = (ptr); (ptr)->prev = (ptr); // } while (0) LinkNode * InitLinkNode() { LinkNode * head = (LinkNode *)malloc(sizeof(LinkNode)); if(head!=NULL) { // head->list.next = head->list.prev = &(head->list); INIT_LIST_HEAD(&(head->list)); } return head; } LinkNode * CreateNode(DataType data) { LinkNode * new = (LinkNode *)malloc(sizeof(LinkNode)); if(new!=NULL) { new->data = data; new->list.next = NULL; new->list.prev = NULL; } return new; } //空链表判断 // static inline int list_empty(struct list_head *head) // { // return head->next == head; // } int InsertNodeHead(LinkNode *head,LinkNode *new) { if(list_empty(&(new->list))||list_empty(&(new->list))) { return 0; } list_add(&(new->list),&(head->list)); return 1; } int InsertNodeTail(LinkNode *head,LinkNode *new) { if(list_empty(&(new->list))||list_empty(&(new->list))) { return 0; } list_add_tail(&(new->list),&(head->list)); return 1; } // * // * 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. // //小结构体指针ptr,大结构体类型type,小结构体在大结构体内部的成员名 // #define list_entry(ptr, type, member) // ((type *)((char *)(ptr)-(unsigned long)(&((type *)0)->member))) //(unsigned long)(&((type *)0)->member)) ---- data -- offset //小结构体的地址-大结构体的地址 void Display1(LinkNode *head) { struct list_head *ptr=NULL; LinkNode *p=NULL; list_for_each(ptr,&(head->list)) { p=list_entry(ptr,LinkNode,list); printf("%d ",p->data); } printf("n"); } //遍历链表的for循环,每一次循环体内得到的就是一个小结构体指针 // #define list_for_each(pos, head) // for (pos = (head)->next; pos != (head); // pos = pos->next) void Display2(LinkNode *head) { struct list_head *ptr=NULL; LinkNode *p=NULL; list_for_each_prev(ptr,&(head->list)) { p=list_entry(ptr,LinkNode,list); printf("%d ",p->data); } printf("n"); } // //安全的遍历,防止在循环体中有对节点的删除操作,这样会导致下一次进入循环体出现段错误 // #define list_for_each_safe(pos, n, head) // for (pos = (head)->next, n = pos->next; pos != (head); // pos = n, n = pos->next) void Display3(LinkNode *head) { struct list_head *ptr=NULL; struct list_head *n=NULL; LinkNode *p=NULL; list_for_each_safe(ptr,n,&(head->list)) { p=list_entry(ptr,LinkNode,list); printf("%d ",p->data); } printf("n"); } //遍历过程中,得到大结构体指针: //pos是遍历过程中的大结构体指针变量, //head是小结构体链表头指针 //member小结构体在大结构体里面的成员名 // #define list_for_each_entry(pos, head, member) // for (pos = list_entry((head)->next, typeof(*pos), member); // &pos->member != (head); // pos = list_entry(pos->member.next, typeof(*pos), member)) void Display4(LinkNode *head) { LinkNode *ptr=NULL; list_for_each_entry(ptr,&(head->list),list) { printf("%d ",ptr->data); } printf("n"); } // #define list_for_each_entry_safe(pos, n, head, member) // 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)) void Display5(LinkNode *head) { LinkNode *ptr=NULL; LinkNode *n=NULL; list_for_each_entry_safe(ptr,n,&(head->list),list) { printf("%d ",ptr->data); } printf("n"); } //取出prev和next节点之间的结点 // static inline void __list_del(struct list_head *prev, struct list_head *next) // { // next->prev = prev; // prev->next = next; // } //取出entry结点:让entry独立出来,前后指针域指向0地址 // static inline void list_del(struct list_head *entry) // { // __list_del(entry->prev, entry->next); // entry->next = (void *) 0; // entry->prev = (void *) 0; // } //删除节点 void DeleteNode(LinkNode *head,DataType data) { struct list_head *ptr=NULL; struct list_head *n=NULL; LinkNode *p=NULL; list_for_each_safe(ptr,n,&(head->list)) { p=list_entry(ptr,LinkNode,list); if(p->data == data) { list_del(&(p->list)); } } } //删除节点 void DeleteNode1(LinkNode *head,DataType data) { LinkNode *ptr=NULL; LinkNode *n=NULL; list_for_each_entry_safe(ptr,n,&(head->list),list) { if(ptr->data==data) { list_del(&(ptr->list)); } } } //查找节点 LinkNode * FindNode(LinkNode *head,DataType data) { LinkNode *ptr=NULL; LinkNode *n=NULL; list_for_each_entry_safe(ptr,n,&(head->list),list) { if(ptr->data==data) { return ptr; } } } //将list链表与head链表进行拼接 //拼接完的链表头是head //比如:list: 1 2 3 4 5 6 7 // head: 11 22 33 44 // 结果:head : 1 2 3 4 5 6 7 11 22 33 44 // static inline void __list_splice(struct list_head *list, // struct list_head *head) // { // struct list_head *first = list->next; // struct list_head *last = list->prev; // struct list_head *at = head->next; // first->prev = head; // head->next = first; // last->next = at; // at->prev = last; // } // static inline void list_splice(struct list_head *list, struct list_head *head) // { // if (!list_empty(list)) // __list_splice(list, head); // } //拼接链表 // list_splice(struct list_head *list, struct list_head *head) // list_splice_init(struct list_head *list,struct list_head *head) void LinkNodeCat(LinkNode *head,LinkNode *List1) { list_splice(&(List1->list),&(head->list)); // list_splice_init(&(List1->list),&(head->list)); } void NodeMove(LinkNode *head,LinkNode *node) { // list_move(&(node->list),&(head->list)); list_move_tail(&(node->list),&(head->list)); } // //移动节点 // list_move(struct list_head *list,struct list_head *head) // list_move_tail(struct list_head *list,struct list_head *head) //将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移动到head前面 // static inline void list_move_tail(struct list_head *list, // struct list_head *head) // { // __list_del(list->prev, list->next); // list_add_tail(list, head); // } int main(int argc, char const *argv[]) { int num=11; LinkNode *head=NULL; LinkNode *list1=NULL; head = InitLinkNode(); list1 = InitLinkNode(); for(int i=1;i<=num;i++) InsertNodeTail(head,CreateNode(i)); for(int i=num+1;i list.h#ifndef __DLIST_H #define __DLIST_H #define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER) #define container_of(ptr, type, member) ({ const typeof( ((type *)0)->member ) *__mptr = (ptr); (type *)( (char *)__mptr - offsetof(type,member) );} #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) } #define LIST_HEAD(name) struct list_head name = LIST_HEAD_INIT(name) //节点结构体指针初始化 #define INIT_LIST_HEAD(ptr) do { (ptr)->next = (ptr); (ptr)->prev = (ptr); } while (0) //将new节点插入到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; } //将new节点插入到head节点后面 static inline void list_add(struct list_head *new, struct list_head *head) { __list_add(new, head, head->next); } //将new节点插入到head的前面 static inline void list_add_tail(struct list_head *new, struct list_head *head) { __list_add(new, head->prev, head); } //取出prev和next节点之间的结点 static inline void __list_del(struct list_head *prev, struct list_head *next) { next->prev = prev; prev->next = next; } //取出entry结点:让entry独立出来,前后指针域指向0地址 static inline void list_del(struct list_head *entry) { __list_del(entry->prev, entry->next); entry->next = (void *) 0; entry->prev = (void *) 0; } //取出entry结点:让entry独立出来,前后指针域指向自己的地址 static inline void list_del_init(struct list_head *entry) { __list_del(entry->prev, entry->next); INIT_LIST_HEAD(entry); } //将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移动到head前面 static inline void list_move_tail(struct list_head *list, struct list_head *head) { __list_del(list->prev, list->next); list_add_tail(list, head); } //空链表判断 static inline int list_empty(struct list_head *head) { return head->next == head; } //将list链表与head链表进行拼接 //拼接完的链表头是head //比如:list: 1 2 3 4 5 6 7 // head: 11 22 33 44 // 结果:head : 1 2 3 4 5 6 7 11 22 33 44 static inline void __list_splice(struct list_head *list, struct list_head *head) { struct list_head *first = list->next; struct list_head *last = list->prev; struct list_head *at = head->next; first->prev = head; head->next = first; last->next = at; at->prev = last; } static inline void list_splice(struct list_head *list, struct list_head *head) { if (!list_empty(list)) __list_splice(list, head); } static inline void list_splice_init(struct list_head *list, struct list_head *head) { if (!list_empty(list)) { __list_splice(list, head); INIT_LIST_HEAD(list); } } //小结构体指针ptr,大结构体类型type,小结构体在大结构体内部的成员名 #define list_entry(ptr, type, member) ((type *)((char *)(ptr)-(unsigned long)(&((type *)0)->member))) //遍历链表的for循环,每一次循环体内得到的就是一个小结构体指针 #define list_for_each(pos, head) for (pos = (head)->next; pos != (head); pos = pos->next) //从后往前遍历 #define list_for_each_prev(pos, head) for (pos = (head)->prev; pos != (head); pos = pos->prev) //安全的遍历,防止在循环体中有对节点的删除操作,这样会导致下一次进入循环体出现段错误 #define list_for_each_safe(pos, n, head) for (pos = (head)->next, n = pos->next; pos != (head); pos = n, n = pos->next) //遍历过程中,得到大结构体指针: //pos是遍历过程中的大结构体指针变量, //head是小结构体链表头指针 //member小结构体在大结构体里面的成员名 #define list_for_each_entry(pos, head, member) for (pos = list_entry((head)->next, typeof(*pos), member); &pos->member != (head); pos = list_entry(pos->member.next, typeof(*pos), member)) #define list_for_each_entry_safe(pos, n, head, member) 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



