一点真实的上下文说得更清楚,下面以红黑树为例,这是
我理解的方式container_of。
正如Documentation/rbtree.txt 所说,在 linux 内核代码中,它不是 rb_node 包含数据
入口,而不是
rbtree 树中的数据节点是包含结构的结构
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 是指向type 实例的member 的指针,此处为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 表示file 中的第 k 行。