内核级数据结构:侵入式链表 (Intrusive List) 之美
学习过数据结构的同学,写出来的链表通常是这样的(非侵入式):
1 | struct Node { |
这种设计的问题在于:它需要两次内存分配(一次给用户数据,一次给节点本身),且节点和数据在内存中是不连续的,对 CPU Cache 极其不友好。
1. 什么是侵入式链表?
侵入式链表(Intrusive List)的思想是:把链表节点直接“埋”在用户数据结构里。
1 | // 链表节点定义(不包含数据!) |
Linux 内核源代码中几乎所有的链表都是这种设计。
2. 黑魔法:container_of
现在问题来了:我们拿到了链表节点 struct list_head *ptr,怎么反推回包含它的 struct Task 的首地址?
我们需要用到 C 语言中最著名的宏之一:container_of。
1 |
原理拆解
offsetof:计算list成员相对于struct Task起始位置的偏移量(字节数)。ptr是当前list成员的地址。ptr - offset,自然就是struct Task的起始地址!
3. 优势分析
3.1 零内存分配 (No Malloc)
链表节点是用户结构体的一部分。当你创建了一个 Task 的时候,节点内存就已经分配好了。把任务加入队列,根本不需要 malloc 新的节点。这对于由于内存碎片而禁止使用堆的嵌入式系统来说,简直是福音。
3.2 缓存友好 (Cache Locality)
虽然节点本身不存数据,但因为节点就嵌在数据结构里,访问完链表指针,紧接着访问数据 (task->pid) 时,数据很大概率已经在 L1 Cache 里了。
3.3 多态且通用
一个数据结构可以同时存在于多个链表中。
1 | struct Task { |
完全不需要修改链表库的代码,也不需要晦涩的 void * 转换。
4. 总结
侵入式链表是 C 语言“指针运算”特性的巅峰应用。它牺牲了一点点类型安全性(还是需要小心强转),换来了极致的性能和灵活性。
- Title: 内核级数据结构:侵入式链表 (Intrusive List) 之美
- Author: Evek Golden
- Created at : 2025-07-05 19:00:00
- Updated at : 2026-06-12 08:57:02
- Link: https://blog.cocodemo.uno/posts/list6n2/
- License: This work is licensed under CC BY-NC-SA 4.0.
Comments