/**内核链表是Linux 内核中最常用的数据结构,代码位于 内核/include/linux/list.h 下
* @file 内核链表实现
* ###############################################
* 内核提供的链式结构体:如下 ##
* //内核链表的节点设计 ##
*struct list_head { ##
* struct list_head *next, *prev; ##
*}; ##
* ###############################################
* 常用接口:
* ----------------------------------------------------------
* 初始化表头
* 方法一:
* name为(struct list_head)类型
* #define LIST_HEAD_INIT(name) { &(name), &(name) }
* 方法二:
*#define LIST_HEAD(name) \
* struct list_head name = LIST_HEAD_INIT(name)
* 方法三:
* static inline void INIT_LIST_HEAD(struct list_head *list)
* ------------------------------------------------------------
* 插入内核链式节点
* 头插法:(实际为将new插入到head后面)
* static inline void list_add(struct list_head *new, struct list_head *head)
*
* 尾插法:(实际为将new插入到head前面)
* static inline void list_add_tail(struct list_head *new, struct list_head *head)
* -------------------------------------------------------------------
* 删除内核链式节点
* static inline void list_del(struct list_head *entry)
* 功能:把内核链式节点entry从其所在的链表中分离出来(不会释放内存)
* --------------------------------------------------------------------
* 判断链表是否为空表
* 简洁判断:
* static inline int list_empty(const struct list_head *head){return head->next == head;}
* 精准判断:
* static inline int list_empty_careful(const struct list_head *head)
*{
* struct list_head *next = head->next;
* return (next == head) && (next == head->prev);
*}
* ---------------------------------------------------------------------
* 遍历链表
* 方法一:遍历所有内核链表链式结构(不包括表头)(pos为内核链表结构体指针)
* #define list_for_each(pos, head) \
* for (pos = (head)->next; pos != (head); \
* pos = pos->next)
* 方法二:常用的遍历方法:(不包括表头)(pos为包含内核链表结构体结构体的指针)
* #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_entry返回解释说明:请观看下面实例
*#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
*通过链表的链式结构,找到所包含链表结构体的指针(type的结构体中包含struct list_head 结构体)返回的是ptr这个链式指针对应的成员指针
*#define container_of(ptr, type, member) ({const typeof( ((type *)0)->member ) *__mptr = (ptr);(type *)( (char *)__mptr - offsetof(type,member) );})
*#define list_entry(ptr, type, member) \
* container_of(ptr, type, member)
*-------------------------------------------------------------------------
* @author your name (you@domain.com)
* @brief
* @version 0.1
* @date 2022-09-03
*
* @copyright Copyright (c) 2022
*
*/
#include<stdio.h>
#include<stdlib.h>
#include"list.h"
/** 使用内核链表需要定义包含内核链式结构体的结构体(如下) **/
/** 数据域 **/ //数据域根据自身需要进行开启
#if 1
#ifndef DATA
#define DATA int
#endif
#endif
struct box
{
//数据域
DATA Data;
//指针域(使用内核链式结构体)
struct list_head list;
};
//初始化表头:方法1:
//LIST_HEAD(Head);
//初始化表头:方法二:
//struct list_head Head = LIST_HEAD_INIT(Head);
int main(void)
{
//初始化表头:方法三:
// struct list_head *Head = malloc(sizeof(struct list_head));
// INIT_LIST_HEAD(Head);
//初始化表头:方法四
struct box *Head = malloc(sizeof(struct box));
INIT_LIST_HEAD(&Head->list);
for(int i = 1; i < 5; i++)
{
//创建新节点
struct box *new = malloc(sizeof(struct box));
//初始化链表数据(数据域处理)
new->Data = i;
//插入节点(指针域处理)(这里是头插)
list_add(&new->list,&Head->list); //循环结束后,链表为 空表头-4-3-2-1 (双向链表)
//插入节点(指针域处理)(这里是尾插)
//list_add_tail(&new->list,&Head->list); //循环结束后,链表为 1-2-3-4-空表头(双向链表)
}
/*****
* 遍历链表方法1:list_for_each遍历链表所有成员的指针域
*(需要通过指针域找到链表成员)使用list_entry
* pos与member两个指针都是访问容器 */
struct list_head *pos = NULL;
struct box *member = NULL;
printf("\nthis is list_for_each to look all\n");
list_for_each(pos,&Head->list)
{
member = list_entry(pos,struct box,list);//通过指针域找到成员指针并返回
printf("%d\t",member->Data);
}
/**遍历链表方法二:list_for_each_entry遍历链表所有成员的指针域
member指针是访问容器 **/
printf("\n\nthis is list_for_each_entry to look all\n");
member = NULL;
list_for_each_entry(member,&Head->list,list)
{
printf("%d\t",member->Data);
}
/**************************************************
* 关于您使用链表的过程中需要:查找,修改等复杂操作
* 只需要使用内核链表的遍历接口来组装,那就可以得到自己
* 想要的接口了!
* *************************************************/
return 0;
}
/*****************
运行结果:(如下)
this is list_for_each to look all
4 3 2 1
this is list_for_each_entry to look all
4 3 2 1
*****************/
内核双向链表的实现
于 2022-09-03 16:22:44 首次发布