linux内核中链表的基本使用_linux链接概念

问题描述:

linux内核中链表的基本使用:
使用LIST_HEAD宏定义链表头
使用list_add向链表添加节点
使用list_for_each_entry遍历链表
使用list_del从链表删除节点
使用list_empty检查链表是否为空
使用list_for_each_entry_safe安全遍历(在删除节点时使用)

日志

添加打印日志信息

分析步骤

第1步:
第2步:
...

代码片段

#include <linux/init.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/list.h>
#include <linux/slab.h>

// 定义链表节点结构 - list成员位置示例(此处放在中间)
struct my_node {
    int data;                  // 节点数据
    int extra_info;            // 额外信息,演示list成员不一定要在最后
    struct list_head list;     // 链表头,可放在结构体任意位置
};

// 定义链表头 - 全局变量
static LIST_HEAD(my_list);

// 从链表中删除指定数据的节点
static void delete_node_with_data(int target) {
    struct my_node *node, *temp;
    bool found = false;

    // 安全遍历链表(允许删除操作)
    list_for_each_entry_safe(node, temp, &my_list, list) {
        if (node->data == target) {
            printk(KERN_INFO "List demo: Found node with data %d, deleting...\n", target);
            /*
                static inline void list_del(struct list_head *entry)
                struct list_head *entry:指向要从链表中删除的节点中 list_head 成员的指针
            */
            list_del(&node->list);  // 从链表中移除
            kfree(node);            // 释放内存
            found = true;
            break;  // 只删除第一个匹配的节点
        }
    }

    if (!found) {
        printk(KERN_INFO "List demo: Node with data %d not found\n", target);
    } else {
        // 删除后打印当前链表状态
        printk(KERN_INFO "List demo: List after deletion:");
        list_for_each_entry(node, &my_list, list) {
            printk(KERN_CONT " %d", node->data);
        }
        printk(KERN_CONT "\n");
    }
}

// 初始化函数 - 插入节点并演示删除
static int __init list_demo_init(void) {
    struct my_node *node;
    int i;

    // 初始化局部链表头
    LIST_HEAD(local_my_list);

    //使用 INIT_LIST_HEAD 宏(常用于动态初始化)
    struct list_head *heap_list = kmalloc(sizeof(struct list_head), GFP_KERNEL);
    INIT_LIST_HEAD(heap_list);  // 初始化链表头(替代LIST_HEAD)


    printk(KERN_INFO "List demo: Initializing\n");

    // 向链表中插入5个节点
    for (i = 0; i < 5; i++) {
        // 分配内存
        node = kmalloc(sizeof(struct my_node), GFP_KERNEL);
        if (!node) {
            printk(KERN_ERR "List demo: Failed to allocate memory\n");
            // 清理已分配的节点(简化处理,实际应完整清理)
            return -ENOMEM;
        }

        // 设置节点数据
        node->data = i + 1;
        node->extra_info = (i + 1) * 10;  // 初始化额外信息
        
        /*
            1. list_add 函数
            作用:将新节点添加到链表的头部(在链表头之后插入)
            static inline void list_add(struct list_head *new, struct list_head *head)
                struct list_head *new:指向新节点中 list_head 成员的指针(要插入的节点的链表项)
                struct list_head *head:指向链表头的指针(要插入到哪个链表)
        */
        // 将节点添加到链表头部,从哪里添加到哪里
        list_add(&node->list, &my_list);
        printk(KERN_INFO "List demo: Added node (data: %d, extra: %d)\n", 
               node->data, node->extra_info);
    }

    // 遍历链表并打印所有节点数据
    printk(KERN_INFO "List demo: Initial list:");

    /*
        list_for_each_entry 宏 define list_for_each_entry(pos, head, member)
        作用:遍历链表中的所有节点,获取包含 list_head 成员的结构体指针(即完整的节点数据)
        pos:循环变量,是指向链表节点结构体的指针(如 struct my_node *node)
        head:指向链表头的指针(遍历的目标链表)
        member:节点结构体中 list_head 成员的变量名(如 list)
    */
   //知道从哪里开始获取到
    list_for_each_entry(node, &my_list, list) {
        printk(KERN_CONT " %d", node->data);
    }
    printk(KERN_CONT "\n");

    // 演示删除操作:删除data=3的节点
    delete_node_with_data(3);

    return 0;
}

// 退出函数 - 清理链表
static void __exit list_demo_exit(void) {
    struct my_node *node, *temp;

    printk(KERN_INFO "List demo: Exiting\n");

    // 遍历并删除所有剩余节点
    list_for_each_entry_safe(node, temp, &my_list, list) {
        printk(KERN_INFO "List demo: Removing node (data: %d, extra: %d)\n",
               node->data, node->extra_info);
        list_del(&node->list);  // 从链表中移除节点
        kfree(node);            // 释放内存
    }

    // 验证链表是否为空
    if (list_empty(&my_list)) {
        printk(KERN_INFO "List demo: List is empty after cleanup\n");
    } else {
        printk(KERN_ERR "List demo: Error - List is not empty after cleanup\n");
    }
}

// 模块注册
module_init(list_demo_init);
module_exit(list_demo_exit);

// 模块信息
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Your Name");
MODULE_DESCRIPTION("Linux kernel list demo with delete operation");
MODULE_VERSION("0.2");

图片

结论

输出结论

待查资料问题

  • 问题 1:?
  • 问题 2:?

参考链接

  • 官方文档
原文链接:,转发请注明来源!