从设备属性读取时调试容器上的简单char驱动程序失败

时间:2014-09-09 09:10:26

标签: c linux linux-kernel kernel linux-device-driver

我正在编写一个访问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

2 个答案:

答案 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);
}