一点真实的上下文说得更清楚,下面以红黑树为例,这是我理解的方式container_of
。
如前所述Documentation/rbtree.txt
,在 linux 内核代码中,它不是 rb_node 包含数据条目,而是
rbtree 树中的数据节点是包含 struct rb_node 成员的结构。
struct vm_area_struct
(在文件中include/linux/mm_types.h:284
)就是这样一个结构,
在同一个文件中,有一个宏rb_entry
定义为
#define rb_entry(ptr, type, member) container_of(ptr, type, member)
显然,rb_entry
与 相同container_of
。
在mm/mmap.c:299
内部函数定义browse_rb
中,有一个用法rb_entry
:
static int browse_rb(struct mm_struct *mm)
{
/* two line code not matter */
struct rb_node *nd, *pn = NULL; /*nd, first arg, i.e. ptr. */
unsigned long prev = 0, pend = 0;
for (nd = rb_first(root); nd; nd = rb_next(nd)) {
struct vm_area_struct *vma;
vma = rb_entry(nd, struct vm_area_struct, vm_rb);
/* -- usage of rb_entry (equivalent to container_of) */
/* more code not matter here */
现在很清楚,在container_of(ptr, type, member)
,
type
是容器结构,这里struct vm_area_struct
member
是type
实例成员的名称,此处vm_rb
为 ,类型为rb_node
,
ptr
member
是一个指向type
实例的指针,这里rb_node *nd
.
做container_of
什么是,就像在这个例子中一样,
- 给定
obj.member
(此处obj.vm_rb
)的地址,返回 的地址obj
。
- 由于结构是一块连续的内存,减号
的地址将是容器的地址。
obj.vm_rb
offset between the struct and member
include/linux/kernel.h:858
-- 定义container_of
include/linux/rbtree.h:51
-- 定义rb_entry
mm/mmap.c:299
-- 用法rb_entry
include/linux/mm_types.h:284
--struct vm_area_struct
Documentation/rbtree.txt:
-- 红黑树的文档
include/linux/rbtree.h:36
-- 定义struct rb_node
附言
以上文件为当前开发版本,即4.13.0-rc7
.
file:k
表示 中的第 k 行file
。