【发布时间】:2021-10-26 07:32:37
【问题描述】:
我浏览了很多关于container_of() 的问题,但没有找到询问如何使用container_of() 在结构中检索结构的问题。如果这个问题是重复的,请指出。很抱歉给您带来不便。
我目前正在实现与另一个内核模块相结合的 PCI 设备驱动程序 remove() 函数,具有以下设置(我删除了一些其他字段以使这个问题易于阅读):
struct my_device {
struct mutex lock;
struct my_dev {
struct cdev cdev;
} my_dev;
struct pci {
struct cdev cdev;
struct pci_dev *pdev;
} pci;
};
问题来了:当我们在struct pci_dev * 类型的struct pci 中有一个指向pdev 的指针时,我们怎么能得到struct pci,然后得到struct my_device? 注意在@987654329 @,我已经将dev分配给了之前分配的struct my_device *dev_ptr,即dev_ptr->pci.pdev = dev;
我尝试了以下方法:
struct pci *pci_t;
pci_t = container_of(ptr, struct pci, pdev)
但这没有用。
报错信息如下:
error: call to '__compiletime_assert_243' declared with attribute error: pointer type mismatch in container_of()
任何想法都将不胜感激。
更新:
我尝试了 cmets 中的方法。由于pci驱动的remove()函数有一个参数——struct pci_dev *dev,代表对应的pci设备,所以我做了如下操作:
struct my_device *mydev;
mydev = container_of(&dev, struct my_device, pci.pdev);
但它没有将指向正确结构的指针返回到mydev。
【问题讨论】:
-
请提供MCVE,说明您是如何使用该宏并显示确切的错误消息。
-
可能不会导致问题,但“
struct pci内指向pdev的指针”必须是struct pci_dev **类型,而不是struct pci_dev* -
@EthanL。如果结构成员的类型为
int,您将需要一个int *指针,对吗?但如果它的类型为int *,则需要一个int **指针。在您的情况下,它的类型为struct pci_dev *,因此您需要一个struct pci_dev **指针。如果您想要一个指向类型的指针,则该指针需要比该类型增加一个间接级别。你真的需要明白这一点。这是 C 语言的基础。 -
所有评论员都遗漏了一个重要的细节,即您在谈论 Linux 内核。因此,正确的解决方案是使用指向
struct pci或更好的struct my_device的特定实例 的指针来填充驱动程序数据。不要用双指针丑化你的代码,所以,拜托!更多阅读:stackoverflow.com/questions/23800337/… -
您应该使用
pci_set_drvdata将指向您的struct my_device(或您的struct pci)的指针与PCI 设备(由struct pci_device *指向)相关联,并使用pci_get_drvdata从 PCI 设备中检索该指针。或者,使用嵌入在struct pci_device中的struct device dev的地址将pci_set_drvdata和pci_get_drvdata替换为dev_set_drvdata和dev_get_drvdata。
标签: c linux-kernel linux-device-driver