我不确定我做错了什么,但现在是时候睁大眼睛了。我创建了一个device_create()
设备提供了一些"额外数据"如下:
pDevice = device_create(ahcip_class, NULL, /*no parent*/
MKDEV(AHCIP_MAJOR, AHCIP_MINOR + i), &mydevs[i],
DRIVER_NAME "%d", AHCIP_MINOR + i);
期望我的sysfs属性函数将指向struct kobject
的{{1}}成员我使用属性函数执行以下操作
struct device
上述函数的输出(浓缩)显示:
static ahcip_dev *get_ahcip_dev(struct kobject *ko)
{
ahcip_dev *adev = NULL;
struct device *pdev = container_of(ko, struct device, kobj);
if (!pdev) {
pr_err("%s:%d unable to find device struct in kobject\n",
__func__, __LINE__);
return NULL;
}
/* some debugging stuff */
pr_info("%s:%d mydevs[0] %p\n", __func__, __LINE__, mydevs);
pr_info("%s:%d mydevs[1] %p\n", __func__, __LINE__, mydevs+1);
pr_info("%s:%d mydevs[0].psysfs_dev %p\n", __func__, __LINE__,
mydevs->psysfs_dev);
pr_info("%s:%d mydevs[1].psysfs_dev %p\n", __func__, __LINE__,
(mydevs + 1)->psysfs_dev);
pr_info("%s:%d pdev %p\n", __func__, __LINE__, pdev);
adev = (ahcip_dev*)dev_get_drvdata(pdev);
/* return the pointer anyway, but if it's null, print to klog */
if (!adev)
pr_err("%s:%d no ahcip_dev, private driver data is NULL\n",
__func__, __LINE__);
return adev;
}
static ssize_t pxis_show(struct kobject *kobj, struct kobj_attribute *attr,
char *buff)
{
u32 pi = 0;
ahcip_dev *adev = get_ahcip_dev(kobj);
/* get_ahcip_dev() will print what happened, this needs to return
* error code
*/
if (!adev)
return -EIO;
pi = adev->port_index;
return sprintf(buff, "%08x\n", get_port_reg(adev->hba->ports[pi], 0x10));
}
在这种情况下,pdev应指向与mydevs [1] .psysfs_dev相同的内存位置,但它的16个字节"更早的"。我做错了什么?
答案 0 :(得分:0)
我不想回答我自己的问题,但在这种情况下这似乎是合适的。问题的根源是对属性函数需要处理的错误假设。属性函数具有此原型you can view in context here
ssize_t (*show)(struct kobject *, struct attribute *,char *);
ssize_t (*store)(struct kobject *,struct attribute *,const char *, size_t);
由于device_create()
函数返回如下定义的struct device
对象(excerpt only, see full def here)
struct device {
struct device *parent;
struct device_private *p;
struct kobject kobj;
...
}
我认为我的属性函数必须处理这个指针。通过对问题描述的阅读表明,当我使用container_of
宏来获取我认为包含struct device
的地址时,我早到16个字节。请注意,此结构的前两个字段是指针。在我的64位系统上,这是16个字节。
因为函数原型定义如上所示,我假设我得到了对kobj
字段的引用。相反,我得到了实际的struct device
对象。换句话说,我在功能输入时获得了我想要的地址,并且仍在尝试找到它。
关于这方面的一些内容可以在Linux内核文档的迷宫中记录。如果有人知道,请在此处输入链接。我读了很多,但没有看到这一个来。我希望这个问题和答案有助于其他一些内核新手。
答案 1 :(得分:0)
您的示例未显示您是如何创建sysfs属性的,也未显示您的pxis_show()
函数与其关联的方式。由于您尝试将此属性连接到struct device
,您是否可能正在调用device_create_file()
来创建sysfs节点?如果是这样,检查struct device_attribute
的回调原型可能更有意义。您将看到show / store回调看起来像:
ssize_t (*show)(struct device *dev, struct device_attribute *attr, char *buf);
ssize_t (*store)(struct device *dev, struct device_attribute *attr,
const char *buf, size_t count);
在哪种情况下可以更好地解释您的额外偏移问题 - 第一个参数实际上已经指向您的struct device
,而不是嵌入式kobj
成员,因此执行container_of()将再带回16个字节。
您可能会将device_attribute
回调与struct sysfs_ops
格式混淆,因为它们看起来相似,但请注意参数类型不同。事实上,从sysfs_ops
到struct device_attribute
的映射可以通过包装函数dev_attr_show
和dev_attr_store
看到,可以找到here