内核双向链表的实现

/**内核链表是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

 *****************/

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值