上下文
我被要求为一个特定的硬件包制作一个字符驱动程序。此驱动程序需要有两个设备位于同一类下。目前,我并没有真正关心整个file_operations结构,因为我主要在sysfs和属性定义方面有问题。我正在开发一个VMware,驱动程序必须能够在linux v.10.X.上运行。
已经做了什么
到目前为止,我已经将我的驱动程序(在任何功能之外(初始化为:
static struct class * dev_class;
static struct device * some_dev_1;
static struct device * some_dev_2;
static struct cdev some_cdev_1;
static struct cdev some_cdev_2;
static dev_t dev_num_1 = MKDEV(MAJOR_NUMBER_1, 0); /* Major is 235 */
static dev_t dev_num_2 = MKDEV(MAJOR_NUMBER_2, 0); /* Major is 240 */
因此,我有两个设备(用于sysfs(和它们的cdev(用于用户界面(。在device_bringup
函数(见下文(中,我想用结构文档中的show/store
方法填充attribute_group ** groups
结构。我试着遵循本教程和本教程,得到了以下代码:
int device_bringup(char * device_1_name, char * device_2_name){
int return_value = SUCCESS;
some_dev_1 = device_create(dev_class, NULL, dev_num_1, NULL, device_1_name); /* Create/Registers it on sysfs */
some_dev_2 = device_create(dev_class, NULL, dev_num_2, NULL, device_2_name);
if(some_dev_1 == NULL){
printk(KERN_ALERT KBUILD_MODNAME " Cannot create the Device #1 !n");
return_value = init_error_manager(1);
}
printk(KERN_ALERT KBUILD_MODNAME " Device #1 was created !n");
if(some_dev_2 == NULL){
printk(KERN_ALERT KBUILD_MODNAME " Cannot create the Device #2 !n");
return_value = init_error_manager(2);
}
printk(KERN_ALERT KBUILD_MODNAME " Device #2 was created !n");
DEVICE_ATTR(first, 0664, sysfs_show, sysfs_store); /* Name should be dev_attr_first */
DEVICE_ATTR(second, 0664, sysfs_show, sysfs_store); /* Name should be dev_attr_second */
struct attribute * some_dev_1_attrs[] = { /* see https://docs.kernel.org/driver-api/driver-model/device.html for info */
&dev_attr_first.attr,
&dev_attr_second.attr,
NULL
};
struct attribute * some_dev_2_attrs[] = {
&dev_attr_first.attr,
&dev_attr_second.attr,
NULL
};
ATTRIBUTE_GROUPS(some_dev_1); /* Create the some_dev_1_groups */
ATTRIBUTE_GROUPS(some_dev_2); /* Create the some_dev_2_groups */
some_dev_1->groups = some_dev_1_groups;
some_dev_2->groups = some_dev_2_groups;
return return_value;
}
问题
在完成了这两个教程之后,我的内核无法构建,我收到了以下错误:
error: initializer element is not constant ATTRIBUTE_GROUPS(some_dev_1);
error: initializer element is not constant ATTRIBUTE_GROUPS(some_dev_2);
然后我阅读了这个问题,它似乎源于some_dev_1
和some_dev_2
设备指针没有初始化的事实。然而,在阅读了一些stackoverflow线程后,我尝试了以下操作:
static struct device * some_dev_1 = kmalloc(sizeof(some_dev_1));
然后
static struct device * some_dev_1 = &(struct device){.name = "test"};
甚至
static struct device * some_dev_1 = NULL;
然而,这些都没有解决这个问题。我确信这个问题很容易解决,但我似乎只能绕着它转
解决方案
事实证明,问题源于宏ATTRIBUTE_GROUPS(some_dev_1)
并没有真正使用范围外定义的some_dev_1
。它只是将其用作组名称的字符串。
使用device_create_with_groups
而不将属性组直接分配给设备,这使它对我有效。我还必须使DEVICE_ATTR
和属性数组为静态,以便它们在范围之外可用。这是最后的工作代码:
int device_bringup(char * device_1_name, char * device_2_name){
int return_value = SUCCESS;
static DEVICE_ATTR(first, 0664, sysfs_show, sysfs_store); /* Name should be dev_attr_tape_deck_first */
static DEVICE_ATTR(second, 0664, sysfs_show, sysfs_store); /* Name should be dev_attr_tape_deck_second */
static struct attribute * some_dev_1_attrs[] = {
&dev_attr_first.attr,
&dev_attr_second.attr,
NULL
};
static struct attribute * some_dev_2_attrs[] = {
&dev_attr_first.attr,
&dev_attr_second.attr,
NULL
};
ATTRIBUTE_GROUPS(some_dev_1);
ATTRIBUTE_GROUPS(some_dev_2);
some_dev_1 = device_create_with_groups(dev_class, NULL, dev_num_1, NULL, some_dev_1_groups, device_1_name);
some_dev_2 = device_create_with_groups(dev_class, NULL, dev_num_2, NULL, some_dev_2_groups, device_2_name);
if(IS_ERR_OR_NULL(some_dev_1)){
printk(KERN_ALERT KBUILD_MODNAME " Cannot create the Device #1 !n");
return_value = PTR_ERR(some_dev_1);
}
printk(KERN_ALERT KBUILD_MODNAME " Device #1 was created !n");
if(IS_ERR_OR_NULL(some_dev_2)){
printk(KERN_ALERT KBUILD_MODNAME " Cannot create the Device #2 !n");
return_value = PTR_ERR(some_dev_2);
}
printk(KERN_ALERT KBUILD_MODNAME " Device #2 was created !n");
return return_value;
}
这不是它的最终版本,因为我必须使函数更加原子化,并且不要在同一个函数中创建两个设备,而是每次调用只创建一个设备。然而,上面的代码解决了我的问题。我希望它能帮助任何遇到这种问题的人。