我正在编写一个访问PCI卡的简单char驱动程序。它在新类的帮助下注册到sysfs。现在我想以方便的方式访问设备的多个参数(即版本,状态,控制...)。我想到了为设备注册多个属性(通过device_create_file()
)。
为此,我创建了自己的设备结构foo_dev
,为此我分配内存并在其中存储所有设备信息(即struct device
)。一旦调用了属性,我想通过使用我的代码中显示的container_of()来恢复我的结构(为了便于阅读而删除了返回验证):
static const ssize_t foo_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct foo_dev *foo_dev = container_of(dev, struct foo_dev,
dev);
mutex_lock(&mutex);
u32 data = ioread32(foo_dev->bar + 0x2020);
mutex_unlock(&mutex);
return sprintf(buf, "%d\n", data);
}
问题:一旦我写入设备,内核就会以Bad IO access at port 0x2020 (return inl(port))
来自ioread32()
来回中止。进一步调查并打印存储在foo_dev
中的其他信息后,我发现结构完全是空的 - container_of()
显然没有重建我的原始结构。为了完整性,请在probe()函数中初始化设备:
...
foo_dev->dev = device_create(fooClass, NULL, foo_dev->devNbr,
foo_dev, DEVICE_NAME);
cdev_init(&foo_dev->cdev, &foo_fops);
rv = cdev_add(&foo_dev->cdev, foo_dev->devNbr, 1);
rv = pci_enable_device(dev);
...
device_create_file(foo_dev->dev, &dev_attr_bar);
...
我可能错了什么?如何在foo_show()中进一步调查我实际收到的struct dev
?
答案 0 :(得分:2)
container_of()
不使用嵌入式指针。
它仅适用于直接嵌入另一个结构的结构:
struct foo_dev {
...
struct device dev;
...
};
(然后你必须使用device_initialize()
。)
答案 1 :(得分:0)
仔细查看device_create()
可以看到初始化设备实际上通过dev_set_drvdata()
在其父结构上获得指针。然后,可以使用container_of()
恢复foodev结构,而不是在属性例程中使用dev_get_drvdata()
。例程变为:
static const ssize_t foo_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct foo_dev *foo_dev = dev_get_drvdata(dev);
mutex_lock(&mutex);
u32 data = ioread32(foo_dev->bar + 0x2020);
mutex_unlock(&mutex);
return sprintf(buf, "%d\n", data);
}