Linux Kernel/通用链表与类型检查

从嵌入的链表节点找回宿主对象

Linux 把 list_head 嵌入业务对象,通过成员偏移找回宿主,并在编译期检查指针类型。

v6.12内存管理核验 2026-10-09
相关概念

工程问题#

通用链表只认识连接指针,调用者却需要操作完整对象;若为每个对象另建包装节点,会增加分配、间接访问和生命周期管理。

实际实现#

list_entry 调用 container_of:从成员指针减去 offsetof 得到宿主起址。static_assert 要求成员类型与指针指向类型相容,或允许 void 指针;这类检查只覆盖类型,不证明指针确实来自那个宿主对象。

处理流程#

  1. 在宿主结构中嵌入 list_head 成员
  2. 链表操作只维护这个成员的前后链接
  3. list_entry 把成员指针交给 container_of
  4. 编译期检查类型,运行时按成员偏移恢复宿主地址

源码片段#

固定版本 · 原文摘录
include/linux/container_of.hv6.12 · L10–L23
查看原文件
10/**11 * container_of - cast a member of a structure out to the containing structure12 * @ptr:	the pointer to the member.13 * @type:	the type of the container struct this is embedded in.14 * @member:	the name of the member within the struct.15 *16 * WARNING: any const qualifier of @ptr is lost.17 */18#define container_of(ptr, type, member) ({				\19	void *__mptr = (void *)(ptr);					\20	static_assert(__same_type(*(ptr), ((type *)0)->member) ||	\21		      __same_type(*(ptr), void),			\22		      "pointer type mismatch in container_of()");	\23	((type *)(__mptr - offsetof(type, member))); })
container_of

完整宏及原始注释:类型断言与 offsetof 地址恢复共同构成接口,原文同时说明 const 限定符会丢失。

include/linux/list.hv6.12 · L594–L601
查看原文件
594/**595 * list_entry - get the struct for this entry596 * @ptr:	the &struct list_head pointer.597 * @type:	the type of the struct this is embedded in.598 * @member:	the name of the list_head within the struct.599 */600#define list_entry(ptr, type, member) \601	container_of(ptr, type, member)
list_entry

链表 API 直接调用 container_of,使嵌入的 list_head 能关联回任意指定的宿主类型。

两段来自同一固定内核版本:第一段给出约束与实现,第二段给出真实容器 API 的使用入口。

收益与取舍#

工程分析

带来的收益

  • 链表无需为每次挂接单独分配包装节点
  • 同一对象可嵌入不同成员参与多条链表
  • 常见的成员指针类型错误可提前暴露

付出的代价

  • 宿主对象布局与容器相耦合;移动或释放对象前必须处理链接关系
  • 同类型的错误成员、悬空指针和伪造地址不会被该类型检查识别
  • 宏依赖内核所用编译器扩展,不能当作可移植 ISO C 模板

可比较的选择

外置包装节点对象无需携带链表字段,但引入额外节点与独立生命周期。

直接保存宿主指针可避免成员反推,却仍需单独的通用容器节点或索引空间。

版本与适用范围#

对应 Linux v6.12 的通用侵入式链表入口与宏定义。container_of 本身不分配内存、不加锁,也不延长对象生命周期;普通 container_of 会丢失 const,需保留限定符时可看同文件的 container_of_const。

参考来源#

源码、官方文档与原始论文
01
linux · list_entry / list_first_entry

include/linux/list.h · list_entry / list_first_entry

源码v6.12
02
linux · container_of / container_of_const

include/linux/container_of.h · container_of / container_of_const

源码v6.12

相关实现与比较#

4 个相关案例
14 个匹配案例