gpt4 book ai didi

c - 如何像在 linux 内核中一样从头开始实现 container_of

转载 作者:塔克拉玛干 更新时间:2023-11-03 01:28:29 26 4
gpt4 key购买 nike

我想从头开始实现 container_of 宏/函数,就像 linux 内核中可用的那样,以从父结构的成员获取父结构的地址。

例如如果父结构是

struct parent{ int id; struct list_head list; };

并且我有结构内 list_head 元素的地址。

所以我想获取父结构的地址,以便我可以访问父结构的 id。

I have only three known information 1. Type of parent structure 2. Type of struct list_head 3. identifire/name of the list_head variable.

#define container_of(ptr, type, member) ({                      \
const typeof( ((type *)0)->member ) *__mptr = (ptr); \
(type *)( (char *)__mptr - offsetof(type,member) );})

感谢我任何人都可以解释。

最佳答案

首先你的问题不合适。据我了解,您想了解宏的工作原理,而不是实现它。

继续前进,

在 linux 内核中使用的链表在 Linux Kernel Linked List Explained 中有很好的解释。

在 linux 内核中,列表包含在列表节点中。示例:

struct list_head {  /* Kernel list structure */
struct list_head *next, *prev;
}

struct my_list {
int to;
struct list_head list; /* list is contained in the node */
int from;
}

因此我们使用 list_head 变量迭代链表。棘手的部分是我们使用列表变量来获取节点结构(其中包含它)

请参阅 MIT FAQ 中的问题 2.14 和 2.15| .这个问题解释了如果我们在结构中有一个变量的偏移量,我们如何检索指向 CONTAINING 结构的指针。

所以通俗地说,我们可以说,

struct s address = <address of struct variable> - <offset of that variable in the struct>

来到宏,考虑宏的这个定义。 (简单的实现,我在 drivers/gpu/drm/nouveau/include/nvif/list.h 中找到)

#define container_of(ptr, type, member) \
(type *)((char *)(ptr) - (char *) &((type *)0)->member)

因此将左操作数视为结构 VARIABLE(这通常是 list_head 变量)。现在来到正确的运营商。为了在包含严格的(比如 struct my_list )中获取该变量(比如 list_head 变量)的 OFFSET,我们创建了一个归零结构(即地址为 0x0 的临时结构),因此结构中任何变量的地址都对应于该变量的偏移量。

现在要理解的最后一部分是为什么转换为 char *。好吧,这个基本的指针算法。 char * addtion 会将值一次递增 1(char* 指向 1 个字节的 char)。

((char*)0) + 1  -> 0x1

如果它是 int * 向指针添加 1 将使偏移量增加 4 ,因为 int * 指向大小为 4 的 int(在我的计算机上)。

((int*)0) + 1  -> 0x4

希望有所帮助.. :)

关于c - 如何像在 linux 内核中一样从头开始实现 container_of,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30868211/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com