嵌套结构体场景下如何正确使用container_of()获取外层结构体指针
问题原因分析
- 第一次编译报错的核心原因:
container_of宏的入参要求是结构体成员变量本身的内存地址,而非成员变量存储的值。你定义的struct pci中pdev成员的类型是struct pci_dev *,该成员自身的地址类型为struct pci_dev **,你传入的ptr是struct pci_dev *类型,和成员地址类型不匹配,因此触发编译类型校验报错。 - 第二次指针无效的核心原因:
remove函数入参dev是栈上临时变量,&dev取的是栈空间地址,并非你预分配的struct my_device结构体内部pci.pdev成员的存储地址,自然无法计算得到正确的结构体起始地址。
正确实现方案
方案1:使用PCI驱动标准私有数据接口(推荐)
这是Linux内核PCI驱动的标准实现逻辑,不需要调用container_of:
- 在
probe函数中完成dev_ptr->pci.pdev = dev赋值后,添加代码:
pci_set_drvdata(dev, dev_ptr);
- 在
remove函数中直接通过入参dev获取外层结构体指针:
struct my_device *mydev = pci_get_drvdata(dev);
方案2:嵌套调用container_of(原理演示用)
如果仅做container_of嵌套使用的原理验证,需要先拿到struct pci内部pdev成员自身的地址(而非pdev存储的指向struct pci_dev的地址),再分两步计算:
// pdev_member_ptr 是 &(my_dev_instance.pci.pdev),类型为 struct pci_dev ** struct pci *pci_t = container_of(pdev_member_ptr, struct pci, pdev); struct my_device *mydev = container_of(pci_t, struct my_device, pci);
由于你在remove函数中拿到的dev是pci.pdev存储的值,而非pci.pdev自身的地址,因此该方案不适用于你当前的PCI驱动场景。
内容的提问来源于stack exchange,提问作者Ethan L.
相关产品推荐
相关产品推荐

