c之关于linux中container_of宏的疑问
为什么要使用 container_of
宏?
container_of(pointer, container_type, container_field);
LDD中说
"This macro takes a pointer to a field named
container_field
, within a structure of typecontainer_type
, and returns a pointer to the containing structure".
我的问题是:
- 如果我们想要一个指向结构(即 container_type)的指针,我们可以 直接分配,对吗?
- 那么为什么它的一个字段的指针被用来分配一个 整个结构的地址?
- 谁能举例说明使用 那个宏?
请您参考如下方法:
举个例子:
struct A
{
int some_data;
int other_data;
};
现在假设有这个函数:
int get_some_data_from_other(int *other)
{
struct A *a = container_of(other, struct A, other_data);
return a->some_data;
}
如您所见,我们可以通过知道指针所在结构的哪个字段来判断包含给定 int *other
的原始 struct A
是什么据说指向。 这里的关键是我们没有对结构本身的引用,而只是指向其成员之一的指针。
这可能看起来很荒谬,但实际上在一些非常聪明的构造中很有用。一个非常常见的例子是内核创建链表的方式。我建议你阅读 this post on kernelnewbies.org .让我们看一个简短的例子:
struct whatever
{
/* whatever data */
struct list_head mylist;
};
所以 struct whatever
有一些数据,但它也想充当链表中的一个节点。他们在学校教你的是有一个不同的结构,它包含 next
/prev
指针以及指向 struct whatever
的指针(或 void *
)。这样,您就有了访问数据的节点。
按照所有软件工程标准,这实际上是一件好事。但是软件工程标准很少考虑 w.r.t 效率。参见 Why should I have written ZeroMQ in C, not C++ (part II) .
底线是,使用传统方法,您必须将链表节点与数据节点分开分配,也就是说,内存分配、释放、碎片和缓存未命中等开销加倍。 Linux 内核的做法恰恰相反。每个数据节点都包含一个通用链表节点。通用链表节点不知道有关数据或数据如何分配的任何信息,只知道如何连接到其他链表节点。
那么让我们深入了解一下:
+-------------------+ +---------------------+ +---------------------+
| | | | | |
| WHATEVER DATA | | WHATEVER DATA 2 | | WHATEVER DATA 3 |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
+-------------------+ +---------------------+ +---------------------+
| |----->| |----->| |
| mylist | | mylist 2 | | mylist 3 |
| |<-----| |<-----| |
+-------------------+ +---------------------+ +---------------------+
作为链表,您拥有的是 struct list_head
中指向其他 struct list_head
的指针。请注意,它们不指向 struct whatever
,而是指向 mylist
inside 这些结构。
假设你有一个节点,struct whatever what
。你想找到下一个节点。你能做什么?首先,您可以执行 w.mylist.next
以获得指向下一个节点的 mylist
的指针。现在您必须能够提取包含该节点的实际 struct whatever
。这就是使用 container_of
的地方:
struct whatever w_next = container_of(w.mylist.next, struct whatever, mylist);
最后,注意Linux内核有宏可以遍历链表的所有节点,这往往是你想要的,所以你实际上不需要直接使用container_of
自己。
1.本站遵循行业规范,任何转载的稿件都会明确标注作者和来源;2.本站的原创文章,请转载时务必注明文章作者和来源,不尊重原创的行为我们将追究责任;3.作者投稿可能会经我们编辑修改或补充。