对于驱动程序开发而言,我对sysfs来说相当新,我似乎在观察一些相当奇怪的行为。总而言之,似乎内核没有将完整的结构传递给我的回调。该驱动器是一个相当简单的SPI-ADC驱动器,用于读取模拟热/电压数据。
现在,我很难相信我在这样一个广泛使用的子系统中发现了Linux内核中的一个错误。我已经在网上搜索了可能有用的任何内容,但所有迹象表明这应该按原样运行。其他传递的结构似乎填充正确,只有attr->attr
成员似乎是NULL
。
我还应该提到这是针对3.2内核的。
那么,简而言之,什么会导致sysfs回调无法接收完全填充的kobj_attribute结构?
示例代码:
static ssize_t ads7960_sysfs_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf)
{
int var, rc, i = 0, j = 0;
long channel = 0;
//DEBUG
printk("%s: kobj->name = %s\n", __func__, kobj->name);
printk("%s: attr = %p\n", __func__, attr);
printk("%s: attr->attr = %p\n", __func__, attr->attr);
printk("%s: attr->attr.name = %s\n", __func__, attr->attr.name);
printk("%s: attr->attr.mode = %o\n", __func__, attr->attr.mode);
/* check for silly things */
if ((attr->attr.name == NULL) || (strlen(attr->attr.name) < 1)) {
printk("%s: invalid channel number. = %s\n", __func__, attr->attr.name);
return -EINVAL;
}
... snip (We never get past here) ...
static struct kobj_attribute ads7960_ch0 = __ATTR(0, 0444, ads7960_sysfs_show, NULL);
static struct kobj_attribute ads7960_ch1 = __ATTR(1, 0444, ads7960_sysfs_show, NULL);
static struct kobj_attribute ads7960_ch2 = __ATTR(2, 0444, ads7960_sysfs_show, NULL);
... snip (there are 12 total ADC channels in the same format) ...
static struct attribute *ch_attrs[] = {
&ads7960_ch0.attr,
&ads7960_ch1.attr,
&ads7960_ch2.attr,
... snip (same 12 channels as above)...
NULL,
};
static struct attribute_group attr_group = {
.attrs = ch_attrs,
};
static struct attribute_group *attr_group_ptr = &attr_group;
... snip ...
static struct spi_driver ads7960_driver = {
.driver = {
.name = "ads7960",
.bus = &spi_bus_type,
.owner = THIS_MODULE,
.groups = &attr_group_ptr,
},
.probe = ads7960_probe,
.remove = __devexit_p(ads7960_remove),
.id_table = ads7960_id,
};
... snip ...
输出已生成:
[root@172.17.152.42: ]# cat /sys/bus/spi/drivers/ads7960/4
[ 65.344789] ads7960_sysfs_show: kobj->name = ads7960
[ 65.350026] ads7960_sysfs_show: attr = dc934000
[ 65.354859] ads7960_sysfs_show: attr->attr = (null)
[ 65.360155] ads7960_sysfs_show: attr->attr.name = (null)
[ 65.365746] ads7960_sysfs_show: attr->attr.mode = 0
[ 65.370861] ads7960_sysfs_show: invalid channel number. = (null)
cat: read error: Invalid argument
参考
http://www.cs.fsu.edu/~baker/devices/lxr/http/source/linux/samples/kobject/kobject-example.c http://kroah.com/log/blog/2013/06/26/how-to-create-a-sysfs-file-correctly/
修改1:
为了总结以下评论,我从sysfs_create_group
手动调用了_init
,并且传递给回调的kobj_attribute
结构似乎已正确填充。回调现在可以正常运行(或修改,就此而言)。如下所述,spi_register_driver
只需拨打sysfs_create_group
。那么,为什么一个人会正确地调用回调而另一个没有呢?
以下评论中,下面是完整的_init
函数和spi_driver
结构。我自己手动创建路径所做的测试是基于第一个参考中的_init
代码而几乎没有修改。
static struct spi_driver ads7960_driver = {
.driver = {
.name = "ads7960",
.bus = &spi_bus_type,
.owner = THIS_MODULE,
.groups = attr_groups,
},
.probe = ads7960_probe,
.remove = __devexit_p(ads7960_remove),
.id_table = ads7960_id,
};
static int __init ads7960_init(void)
{
return spi_register_driver(&ads7960_driver);
}
module_init(ads7960_init);
答案 0 :(得分:1)
.groups
struct device_driver
成员必须指向以NULL结尾的属性组指针列表,而不是指向属性组的单个指针。因此,您需要:{/ p>而不是attr_group_ptr
static struct attribute_group *attr_groups[] = { &attr_group, NULL };
......然后
static struct spi_driver ads7960_driver = {
.driver = {
.name = "ads7960",
.bus = &spi_bus_type,
.owner = THIS_MODULE,
.groups = attr_groups,
},
但是,有一个辅助宏可以声明属性组和属性组列表,而不是:
static struct attribute *ch_attrs[] = {
&ads7960_ch0.attr,
&ads7960_ch1.attr,
&ads7960_ch2.attr,
/* ... */
NULL,
};
ATTRIBUTE_GROUPS(ch); /* declares ch_group and ch_groups */
static struct spi_driver ads7960_driver = {
.driver = {
.name = "ads7960",
.bus = &spi_bus_type,
.owner = THIS_MODULE,
.groups = ch_groups,
},