c/c++语言开发共享怀疑linux中的container_of宏

为什么我们使用container_of宏?

 container_of(pointer, container_type, container_field); 

据LDD说

“这个宏在一个类型为container_field的结构中接受一个名为container_field的字段的指针,并返回一个指向包含结构的指针”。

我的问题是:

    让我给你举个例子:

     struct A { int some_data; int other_data; }; 

    现在让我们说有这个function:

     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 这里的关键是我们没有对结构本身的引用,而只是指向其成员之一的指针

    这看起来很荒谬,但实际上在一些非常聪明的结构中很有用。 一个非常常见的例子是内核创建链表的方式。 我建议你在kernelnewbies.org上阅读这篇文章 。 让我们看一个简短的例子:

     struct whatever { /* whatever data */ struct list_head mylist; }; 

    所以struct whatever具有一些数据的东西,但它也希望充当链表中的节点。 他们在学校教你的是拥有一个不同的结构,包含next / prev指针以及指向struct whatever (或void * )的指针。 这样,您就拥有了通过其获取数据的节点。

    按照所有软件工程标准,这实际上是一件好事。 但软件工程标准对效率的要求很低。 请参阅为什么我应该用C编写ZeroMQ,而不是C ++(第二部分) 。

    底线是,使用传统方法,您必须与数据节点分开分配链接列表节点,即您将内存分配,解除分配,碎片和缓存未命中等的开销加倍。 Linux内核的方式恰恰相反。 每个数据节点都包含一个通用链表节点。 通用链表节点不知道有关数据或它们如何分配的任何信息,只知道如何连接到其他链表节点。

    让我们深入了解一下:

      +-------------------+ +---------------------+ +---------------------+ | | | | | | | WHATEVER DATA | | WHATEVER DATA 2 | | WHATEVER DATA 3 | | | | | | | | | | | | | | | | | | | | | | | | | +-------------------+ +---------------------+ +---------------------+ | |----->| |----->| | | mylist | | mylist 2 | | mylist 3 | | |<-----| |<-----| | +-------------------+ +---------------------+ +---------------------+ 

    你所拥有的链表是struct list_head中指向其他struct list_head的指针。 请注意,它们并不指向struct whatever ,而是指向那些结构中的mylist

    假设你有一个节点, struct whatever w 。 您想要找到下一个节点。 你能做什么? 首先,您可以执行w.mylist.next以获取指向下一个节点的mylist的指针。 现在,您必须能够提取包含该节点的实际struct whatever 。 这就是使用container_of的地方:

     struct whatever w_next = container_of(w.mylist.next, struct whatever, mylist); 

    最后,请注意Linux内核具有遍历链表的所有节点的宏,这通常不是您想要的,因此您实际上不需要自己直接使用container_of

     Why do we use container_of macro ? 

    容器的宏用于获取指向包含元素的结构的开头的指针。

    例如

     struct container { int some_other_data; int this_data; } 

    并且指针int *my_ptr指向this_data成员,您将使用宏来获取指向struct container *my_container的指针:

     struct container *my_container; my_container = container_of(my_ptr, struct container, this_data); 

    this_data的偏移量考虑到结构的开头对于获取正确的指针位置至关重要。

    实际上,您只需从指针my_ptr减去成员this_data的偏移量即可获得正确的位置。

    另见这里清楚你的疑惑。

    是的,您可以使用自己编写的演员/作业,但它有一些优点。

    效率 – 使用宏而不是声明整个演员表并不容易吗?

    维护 – 如果每个人都使用宏,只需编辑宏,就可以在整个项目中轻松更改指针分配的方式。

    可读性 – 什么是易读的? 一个明确的演员或宏为你做的?

    安全性 – 您可能相信此宏可以工作,并且它运行任何重要的强制转换和类型检查,比您自己的代码更好。

      以上就是c/c++开发分享怀疑linux中的container_of宏相关内容,想了解更多C/C++开发(异常处理)及C/C++游戏开发关注计算机技术网(www.ctvol.com)!)。

      本文来自网络收集,不代表计算机技术网立场,如涉及侵权请联系管理员删除。

      ctvol管理联系方式QQ:251552304

      本文章地址:https://www.ctvol.com/c-cdevelopment/518774.html

      (0)
      上一篇 2020年12月4日
      下一篇 2020年12月4日

      精彩推荐