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");
}


/**
* list_for_each_entry_safe – iterate over list of given type safe against removal of list entry
* @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)            \
// 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 <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#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");
}


/**
* list_for_each    -    iterate over a list
* @pos:    the &struct list_head to use as a loop counter.
* @head:    the head for your list.
*/

//遍历链表的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");
}


/**
* list_for_each_entry_safe – iterate over list of given type safe against removal of list entry
* @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)            \
// 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");
}


/*
* 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!
*/
//取出prev和next节点之间的结点
// 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.
*/
//取出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;
// }

/**
* list_splice – join two lists
* @list: the new list to add.
* @head: the place to add it in the first list.
*/
// 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_move – delete from one list and add as another’s head
* @list: the entry to move
* @head: the head that will precede our 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_move_tail – delete from one list and add as another’s tail
* @list: the entry to move
* @head: the head that will follow our entry
*/
//将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<num+10;i++)
		InsertNodeHead(list1,CreateNode(i));

	Display1(list1);
	DeleteNode(head,5);
	// DeleteNode1(head,6);
	LinkNodeCat(head,list1);

	Display1(head);
	// Display2(head);
	// Display3(head);
	// Display4(head);
	// Display5(head);


	return 0;
}
list.h
#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
 *
 * @ptr:	the pointer to the member.
 * @type:	the type of the container struct this is embedded in.
 * @member:	the name of the member within the struct.
 *
 */
#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) );}
/*
 * 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) }

#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)

/*
* Insert a new entry between two known consecutive entries.
*
* This is only for internal list manipulation where we know
* the prev/next entries already!
*/

//将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;
}

/**
* 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.
*/
//将new节点插入到head节点后面
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.
*/
//将new节点插入到head的前面
static inline void list_add_tail(struct list_head *new, struct list_head *head)
{
	__list_add(new, head->prev, head);
}

/*
* 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!
*/
//取出prev和next节点之间的结点
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.
*/
//取出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;
}

/**
* list_del_init – deletes entry from list and reinitialize it.
* @entry: the element to delete from the list.
*/
//取出entry结点:让entry独立出来,前后指针域指向自己的地址
static inline void list_del_init(struct list_head *entry)
{
	__list_del(entry->prev, entry->next);
	INIT_LIST_HEAD(entry);
}

/**
* list_move – delete from one list and add as another’s head
* @list: the entry to move
* @head: the head that will precede our 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_move_tail – delete from one list and add as another’s tail
* @list: the entry to move
* @head: the head that will follow our entry
*/
//将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);
}

/**
* list_empty – tests whether a list is empty
* @head: the list to test.
*/
//空链表判断
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;
}

/**
* list_splice – join two lists
* @list: the new list to add.
* @head: the place to add it in the first list.
*/
static inline void list_splice(struct list_head *list, struct list_head *head)
{
if (!list_empty(list))
__list_splice(list, head);
}

/**
* list_splice_init – join two lists and reinitialise the emptied list.
* @list: the new list to add.
* @head: the place to add it in the first list.
*
* The list at @list is reinitialised
*/
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);
}
}

/**
* 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)))
//小结构体的地址 - 偏移量 = 大结构体的地址

/**
* list_for_each    -    iterate over a list
* @pos:    the &struct list_head to use as a loop counter.
* @head:    the head for your list.
*/

//遍历链表的for循环,每一次循环体内得到的就是一个小结构体指针
#define list_for_each(pos, head) \
for (pos = (head)->next; pos != (head); \
pos = pos->next)

/**
* list_for_each_prev    -    iterate over a list backwards
* @pos:    the &struct list_head to use as a loop counter.
* @head:    the head for your list.
*/
//从后往前遍历
#define list_for_each_prev(pos, head) \
for (pos = (head)->prev; pos != (head); \
pos = pos->prev)

/**
* list_for_each_safe    -    iterate over a list safe against removal of list entry
* @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
* @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.
*/
//遍历过程中,得到大结构体指针:
//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))

/**
* list_for_each_entry_safe – iterate over list of given type safe against removal of list entry
* @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)            \
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
  • 4
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
一、linux内核链表 1、普通链表的数据区域的局限性 之前定义数据区域时直接int data,我们认为我们的链表中需要存储的是一个int类型的数。但是实际上现实编程中链接中的节点不可能这么简单,而是多种多样的。 一般实际项目中的链表,节点中存储的数据其实是一个结构体,这个结构体中包含若干的成员,这些成员加起来构成了我们的节点数据区域。 2、一般性解决思路:即把数据区封装为一个结构体 (1)因为链表实际解决的问题是多种多样的,所以内部数据区域的结构体构成也是多种多样的。 这样也导致了不同程序当中的链表总体构成是多种多样的。 我们无法通过一套泛性的、普遍适用的操作函数来访问所有的链表,意味着我们设计一个链表就得写一套链表的操作函数(节点创建、插入、删除、遍历……)。 (2)实际上深层次分析会发现 不同的链表虽然这些方法不能通用需要单独写,但是实际上内部的思路和方法是相同的,只是函数的局部地区有不同。 实际上链表操作是相同的,而涉及到数据区域的操作就有不同 (3)问题 能不能有一种办法把所有链表中操作方法里共同的部分提取出来用一套标准方法实现,然后把不同的部分留着让具体链表的实现者自己去处理。 3、内核链表的设计思路 (1)内核链表中实现一个纯链表封装,以及纯链表的各种操作函数 纯链表就是没有数据区域,只有前后向指针; 各种操作函数是节点创建、插入、删除、遍历。 这个纯链表本身自己没有任何用处,它的用法是给我们具体链表作为核心来调用。 4、list.h文件简介 (1)内核中核心纯链表的实现在include/linux/list.h文件中 (2)list.h中就是一个纯链表的完整封装,包含节点定义和各种链表操作方法。 二、内核链表的基本算法和使用简介 1、内核链表的节点创建、删除、遍历等 2、内核链表的使用实践 (1)问题:内核链表只有纯链表,没有数据区域,怎么使用? 使用方法是将内核链表作为将来整个数据结构的结构体的一个成员内嵌进去。类似于公司收购,实现被收购公司的功能。 这里面要借助container_of宏。
Linux内核中的链表是一种常用的数据结构,它在内核中被广泛使用来组织和管理数据。链表使用双链表的形式,每个节点只包含指针域,没有数据域。在Linux内核中,链表的操作接口定义在`linux/list.h`头文件中。为了方便使用,内核提供了多种初始化链表的方式。宏定义是一种常用的初始化链表的方式,其中的一个宏定义是`INIT_LIST_HEAD(ptr)`。这个宏被用来初始化一个链表节点,将其next和prev指针都指向自身,表示这是一个空链表。通过这样的方式,可以方便地对链表进行插入和删除操作,以及遍历链表中的元素。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [Linux内核链表理解与使用](https://blog.csdn.net/to_be_better_wen/article/details/127720433)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 33.333333333333336%"] - *2* [linux内核链表最细讲解](https://blog.csdn.net/yzw_yy/article/details/130094799)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 33.333333333333336%"] - *3* [Linux中的内核链表实例详解](https://download.csdn.net/download/weixin_38724363/14893522)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 33.333333333333336%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Yengi

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值