Linux链表操作全解析
Linux C语言链表深度解析与实战技巧
- 一、链表基础概念与内核链表优势
- 1.1 为什么使用链表?
- 1.2 Linux 内核链表与用户态链表的区别
- 二、内核链表结构与宏解析
- 常用宏/函数
- 三、内核链表的优点
- 四、用户态链表示例
- 五、双向循环链表在内核中的实现优势
- 5.1 插入效率
- 5.2 安全遍历删除
- 六、典型应用场景
- 七、调试技巧与常见陷阱
- 7.1 打印链表内容
- 7.2 常见错误
- 八、实战案例:Linux 内核模块中的链表使用
- 8.1 模块源码
- 8.2 Makefile 编译模块
- 8.3 插入与卸载模块
- 九、总结:开发建议
本文系统讲解 Linux 下 C 语言链表的使用原理、最佳实践及内核模块中的实战示例,适合嵌入式开发者、驱动工程师和系统软件开发者。
一、链表基础概念与内核链表优势
1.1 为什么使用链表?
- 动态插入/删除效率高(相比数组不需要整体移动元素)
- 内存利用率高(按需分配)
- 常用于队列、任务调度、资源池、驱动设备列表等场景
1.2 Linux 内核链表与用户态链表的区别
项目 | 用户态实现 | 内核态实现 |
---|---|---|
指针结构 | 自定义指针结构 | 使用 struct list_head |
安全性 | 程序员自行维护 | 提供安全宏/内联函数 |
插入/删除API | 手动实现 | 提供统一接口如 list_add |
迭代方式 | 手动循环 | 宏如 list_for_each_entry |
二、内核链表结构与宏解析
struct list_head {struct list_head *next, *prev;
};
常用宏/函数
INIT_LIST_HEAD(ptr)
list_add(new, head)
:头插法list_add_tail(new, head)
:尾插法list_del(entry)
list_empty(head)
list_for_each_entry(pos, head, member)
list_for_each_entry_safe(pos, n, head, member)
三、内核链表的优点
- 双向循环结构:从任意节点出发都能遍历完整链表
- 插入删除不涉及内容拷贝:仅修改指针
- 接口统一、安全可靠:可结合
container_of
获取真实结构体指针
四、用户态链表示例
#include <stdio.h>
#include <stdlib.h>
#include <string.h>typedef struct student {int id;char name[20];struct student *next;
} student_t;void add_student(student_t **head, int id, const char *name) {student_t *new_node = malloc(sizeof(student_t));new_node->id = id;strncpy(new_node->name, name, sizeof(new_node->name));new_node->next = *head;*head = new_node;
}void print_students(student_t *head) {while (head) {printf("ID: %d, Name: %s\n", head->id, head->name);head = head->next;}
}
五、双向循环链表在内核中的实现优势
5.1 插入效率
在头部插入只需两次指针操作:
list_add(&new_node->list, &head);
5.2 安全遍历删除
list_for_each_entry_safe(ptr, tmp, &head, list) {list_del(&ptr->list);kfree(ptr);
}
六、典型应用场景
场景 | 描述 |
---|---|
设备驱动管理 | 管理设备结构体(如 net_device) |
定时器链表 | 内核定时器统一调度 |
slab 分配器链表 | 管理对象缓存池 |
进程调度/等待队列 | 管理 PCB / wait queue |
协议栈管理 | TCP/UDP 的 socket 链表 |
七、调试技巧与常见陷阱
7.1 打印链表内容
#define print_list(head) \list_for_each_entry(ptr, head, list) \printk(KERN_INFO "Node: %s\n", ptr->name);
7.2 常见错误
- 忘记初始化
INIT_LIST_HEAD
- 使用已释放节点(UAF)
- 非安全删除遍历(未使用
list_for_each_entry_safe
)
八、实战案例:Linux 内核模块中的链表使用
8.1 模块源码
// mylist_module.c
#include <linux/init.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/slab.h>
#include <linux/list.h>MODULE_LICENSE("GPL");struct student {int id;char name[20];struct list_head list;
};static LIST_HEAD(student_list);static int __init mylist_init(void)
{int i;struct student *stu;printk(KERN_INFO "Loading student list module...\n");for (i = 1; i <= 5; ++i) {stu = kmalloc(sizeof(*stu), GFP_KERNEL);stu->id = i;snprintf(stu->name, sizeof(stu->name), "Student%d", i);INIT_LIST_HEAD(&stu->list);list_add_tail(&stu->list, &student_list);}return 0;
}static void __exit mylist_exit(void)
{struct student *stu, *tmp;printk(KERN_INFO "Unloading student list module...\n");list_for_each_entry_safe(stu, tmp, &student_list, list) {list_del(&stu->list);kfree(stu);}
}module_init(mylist_init);
module_exit(mylist_exit);
8.2 Makefile 编译模块
obj-m += mylist_module.oall:make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modulesclean:make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean
8.3 插入与卸载模块
$ make
$ sudo insmod mylist_module.ko
$ dmesg | tail -n 10
$ sudo rmmod mylist_module
$ dmesg | tail -n 10
九、总结:开发建议
建议项 | 内容 |
---|---|
一定初始化链表头 | 使用 INIT_LIST_HEAD 初始化 |
删除节点用安全宏 | list_for_each_entry_safe 防止遍历时删除崩溃 |
内存管理责任明确 | kmalloc/kfree 成对使用 |
多线程环境加锁 | 必要时配合 spinlock 或 mutex |
定位 bug 用 printk | 输出 prev , next , 数据字段调试链表结构 |
本文涵盖了从用户态链表构造到 Linux 内核模块链表的实战应用,帮助你在驱动开发和内核开发中熟练掌握链表的构造与使用。
相关文章:
Linux链表操作全解析
Linux C语言链表深度解析与实战技巧 一、链表基础概念与内核链表优势1.1 为什么使用链表?1.2 Linux 内核链表与用户态链表的区别 二、内核链表结构与宏解析常用宏/函数 三、内核链表的优点四、用户态链表示例五、双向循环链表在内核中的实现优势5.1 插入效率5.2 安全…...

智慧医疗能源事业线深度画像分析(上)
引言 医疗行业作为现代社会的关键基础设施,其能源消耗与环境影响正日益受到关注。随着全球"双碳"目标的推进和可持续发展理念的深入,智慧医疗能源事业线应运而生,致力于通过创新技术与管理方案,重构医疗领域的能源使用模式。这一事业线融合了能源管理、可持续发…...

Lombok 的 @Data 注解失效,未生成 getter/setter 方法引发的HTTP 406 错误
HTTP 状态码 406 (Not Acceptable) 和 500 (Internal Server Error) 是两类完全不同的错误,它们的含义、原因和解决方法都有显著区别。以下是详细对比: 1. HTTP 406 (Not Acceptable) 含义: 客户端请求的内容类型与服务器支持的内容类型不匹…...
应用升级/灾备测试时使用guarantee 闪回点迅速回退
1.场景 应用要升级,当升级失败时,数据库回退到升级前. 要测试系统,测试完成后,数据库要回退到测试前。 相对于RMAN恢复需要很长时间, 数据库闪回只需要几分钟。 2.技术实现 数据库设置 2个db_recovery参数 创建guarantee闪回点,不需要开启数据库闪回。…...
论文解读:交大港大上海AI Lab开源论文 | 宇树机器人多姿态起立控制强化学习框架(二)
HoST框架核心实现方法详解 - 论文深度解读(第二部分) 《Learning Humanoid Standing-up Control across Diverse Postures》 系列文章: 论文深度解读 + 算法与代码分析(二) 作者机构: 上海AI Lab, 上海交通大学, 香港大学, 浙江大学, 香港中文大学 论文主题: 人形机器人…...

微信小程序之bind和catch
这两个呢,都是绑定事件用的,具体使用有些小区别。 官方文档: 事件冒泡处理不同 bind:绑定的事件会向上冒泡,即触发当前组件的事件后,还会继续触发父组件的相同事件。例如,有一个子视图绑定了b…...
ES6从入门到精通:前言
ES6简介 ES6(ECMAScript 2015)是JavaScript语言的重大更新,引入了许多新特性,包括语法糖、新数据类型、模块化支持等,显著提升了开发效率和代码可维护性。 核心知识点概览 变量声明 let 和 const 取代 var…...

RocketMQ延迟消息机制
两种延迟消息 RocketMQ中提供了两种延迟消息机制 指定固定的延迟级别 通过在Message中设定一个MessageDelayLevel参数,对应18个预设的延迟级别指定时间点的延迟级别 通过在Message中设定一个DeliverTimeMS指定一个Long类型表示的具体时间点。到了时间点后…...

CTF show Web 红包题第六弹
提示 1.不是SQL注入 2.需要找关键源码 思路 进入页面发现是一个登录框,很难让人不联想到SQL注入,但提示都说了不是SQL注入,所以就不往这方面想了 先查看一下网页源码,发现一段JavaScript代码,有一个关键类ctfs…...

docker详细操作--未完待续
docker介绍 docker官网: Docker:加速容器应用程序开发 harbor官网:Harbor - Harbor 中文 使用docker加速器: Docker镜像极速下载服务 - 毫秒镜像 是什么 Docker 是一种开源的容器化平台,用于将应用程序及其依赖项(如库、运行时环…...
java_网络服务相关_gateway_nacos_feign区别联系
1. spring-cloud-starter-gateway 作用:作为微服务架构的网关,统一入口,处理所有外部请求。 核心能力: 路由转发(基于路径、服务名等)过滤器(鉴权、限流、日志、Header 处理)支持负…...

label-studio的使用教程(导入本地路径)
文章目录 1. 准备环境2. 脚本启动2.1 Windows2.2 Linux 3. 安装label-studio机器学习后端3.1 pip安装(推荐)3.2 GitHub仓库安装 4. 后端配置4.1 yolo环境4.2 引入后端模型4.3 修改脚本4.4 启动后端 5. 标注工程5.1 创建工程5.2 配置图片路径5.3 配置工程类型标签5.4 配置模型5.…...
利用ngx_stream_return_module构建简易 TCP/UDP 响应网关
一、模块概述 ngx_stream_return_module 提供了一个极简的指令: return <value>;在收到客户端连接后,立即将 <value> 写回并关闭连接。<value> 支持内嵌文本和内置变量(如 $time_iso8601、$remote_addr 等)&a…...
CVPR 2025 MIMO: 支持视觉指代和像素grounding 的医学视觉语言模型
CVPR 2025 | MIMO:支持视觉指代和像素对齐的医学视觉语言模型 论文信息 标题:MIMO: A medical vision language model with visual referring multimodal input and pixel grounding multimodal output作者:Yanyuan Chen, Dexuan Xu, Yu Hu…...

python打卡day49
知识点回顾: 通道注意力模块复习空间注意力模块CBAM的定义 作业:尝试对今天的模型检查参数数目,并用tensorboard查看训练过程 import torch import torch.nn as nn# 定义通道注意力 class ChannelAttention(nn.Module):def __init__(self,…...

基于FPGA的PID算法学习———实现PID比例控制算法
基于FPGA的PID算法学习 前言一、PID算法分析二、PID仿真分析1. PID代码2.PI代码3.P代码4.顶层5.测试文件6.仿真波形 总结 前言 学习内容:参考网站: PID算法控制 PID即:Proportional(比例)、Integral(积分&…...
<6>-MySQL表的增删查改
目录 一,create(创建表) 二,retrieve(查询表) 1,select列 2,where条件 三,update(更新表) 四,delete(删除表…...

大话软工笔记—需求分析概述
需求分析,就是要对需求调研收集到的资料信息逐个地进行拆分、研究,从大量的不确定“需求”中确定出哪些需求最终要转换为确定的“功能需求”。 需求分析的作用非常重要,后续设计的依据主要来自于需求分析的成果,包括: 项目的目的…...
云计算——弹性云计算器(ECS)
弹性云服务器:ECS 概述 云计算重构了ICT系统,云计算平台厂商推出使得厂家能够主要关注应用管理而非平台管理的云平台,包含如下主要概念。 ECS(Elastic Cloud Server):即弹性云服务器,是云计算…...

51c自动驾驶~合集58
我自己的原文哦~ https://blog.51cto.com/whaosoft/13967107 #CCA-Attention 全局池化局部保留,CCA-Attention为LLM长文本建模带来突破性进展 琶洲实验室、华南理工大学联合推出关键上下文感知注意力机制(CCA-Attention),…...

Prompt Tuning、P-Tuning、Prefix Tuning的区别
一、Prompt Tuning、P-Tuning、Prefix Tuning的区别 1. Prompt Tuning(提示调优) 核心思想:固定预训练模型参数,仅学习额外的连续提示向量(通常是嵌入层的一部分)。实现方式:在输入文本前添加可训练的连续向量(软提示),模型只更新这些提示参数。优势:参数量少(仅提…...

树莓派超全系列教程文档--(61)树莓派摄像头高级使用方法
树莓派摄像头高级使用方法 配置通过调谐文件来调整相机行为 使用多个摄像头安装 libcam 和 rpicam-apps依赖关系开发包 文章来源: http://raspberry.dns8844.cn/documentation 原文网址 配置 大多数用例自动工作,无需更改相机配置。但是,一…...

Spark 之 入门讲解详细版(1)
1、简介 1.1 Spark简介 Spark是加州大学伯克利分校AMP实验室(Algorithms, Machines, and People Lab)开发通用内存并行计算框架。Spark在2013年6月进入Apache成为孵化项目,8个月后成为Apache顶级项目,速度之快足见过人之处&…...
Java 语言特性(面试系列1)
一、面向对象编程 1. 封装(Encapsulation) 定义:将数据(属性)和操作数据的方法绑定在一起,通过访问控制符(private、protected、public)隐藏内部实现细节。示例: public …...
进程地址空间(比特课总结)
一、进程地址空间 1. 环境变量 1 )⽤户级环境变量与系统级环境变量 全局属性:环境变量具有全局属性,会被⼦进程继承。例如当bash启动⼦进程时,环 境变量会⾃动传递给⼦进程。 本地变量限制:本地变量只在当前进程(ba…...

css实现圆环展示百分比,根据值动态展示所占比例
代码如下 <view class""><view class"circle-chart"><view v-if"!!num" class"pie-item" :style"{background: conic-gradient(var(--one-color) 0%,#E9E6F1 ${num}%),}"></view><view v-else …...
脑机新手指南(八):OpenBCI_GUI:从环境搭建到数据可视化(下)
一、数据处理与分析实战 (一)实时滤波与参数调整 基础滤波操作 60Hz 工频滤波:勾选界面右侧 “60Hz” 复选框,可有效抑制电网干扰(适用于北美地区,欧洲用户可调整为 50Hz)。 平滑处理&…...
Leetcode 3576. Transform Array to All Equal Elements
Leetcode 3576. Transform Array to All Equal Elements 1. 解题思路2. 代码实现 题目链接:3576. Transform Array to All Equal Elements 1. 解题思路 这一题思路上就是分别考察一下是否能将其转化为全1或者全-1数组即可。 至于每一种情况是否可以达到…...
ubuntu搭建nfs服务centos挂载访问
在Ubuntu上设置NFS服务器 在Ubuntu上,你可以使用apt包管理器来安装NFS服务器。打开终端并运行: sudo apt update sudo apt install nfs-kernel-server创建共享目录 创建一个目录用于共享,例如/shared: sudo mkdir /shared sud…...
椭圆曲线密码学(ECC)
一、ECC算法概述 椭圆曲线密码学(Elliptic Curve Cryptography)是基于椭圆曲线数学理论的公钥密码系统,由Neal Koblitz和Victor Miller在1985年独立提出。相比RSA,ECC在相同安全强度下密钥更短(256位ECC ≈ 3072位RSA…...