如何为平台驱动程序正确初始化属性组?

编辑#4:我想,我不应该将attr_groups分配给struct platform_driver结构的driver字段中的groups字段。 寻找评论/* WRONGO: should not be assigned here. */ /* WRONGO: should not be assigned here. */下面。

我还没有想出我应该把它分配到哪里…


我的平台驱动程序的代码在读取sysfs属性时,由于NULL引用而导致内核“OOPS”。 我确定这是一个简单的监督下面的代码,但我看不到它:

 ... static int samples_per_frame = SAMPLE_CHANNEL_COUNT; DEVICE_INT_ATTR(samples_per_frame, S_IRUGO | S_IWUSR, samples_per_frame); static struct attribute *attrs[] = { &dev_attr_samples_per_frame.attr.attr, NULL, }; static struct attribute_group attr_group = { .attrs = attrs, }; static const struct attribute_group *attr_groups[] = { &attr_group, NULL, }; static struct platform_driver platform = { .remove = my_remove, .probe = my_probe, .driver = { .name = DRIVER_NAME, .owner = THIS_MODULE, .groups = attr_groups, /* WRONGO: should not be assigned here. */ .of_match_table = of_match, }, }; ... 

(Linux 3.12),当模块被加载时,安装和探测运行平稳,属性出现在sysfs中,但是当我尝试读取它时,会发生内核“oops”。

 /sys/bus/platform/drivers/my_driver# ls ff250000.my_driver samples_per_frame uevent /sys/bus/platform/drivers/my_driver# /sys/bus/platform/drivers/my_driver# cat samples_per_frame Unable to handle kernel NULL pointer dereference at virtual address 00000000 pgd = bf1e0000 [00000000] *pgd=3f1d8831, *pte=00000000, *ppte=00000000 Internal error: Oops: 17 [#1] SMP ARM Modules linked in: my_driver(O) CPU: 1 PID: 194 Comm: cat Tainted: GO 3.12.0 #6 task: bf054000 ti: bf194000 task.ti: bf194000 PC is at device_show_int+0x2c/0x38 LR is at drv_attr_show+0x2c/0x38 pc : [<80308f58>] lr : [<8030b6fc>] psr: a0000013 sp : bf195ee8 ip : 00000d58 fp : bf195ef4 r10: bf1d1380 r9 : 7e946c20 r8 : bf195f78 r7 : bf1d13d8 r6 : bf1d13c0 r5 : bfbc9e00 r4 : 8055d520 r3 : 00000000 r2 : 80620d58 r1 : 00001000 r0 : bf190000 Flags: NzCv IRQs on FIQs on Mode SVC_32 ISA ARM Segment user Control: 10c5387d Table: 3f1e004a DAC: 00000015 Process cat (pid: 194, stack limit = 0xbf194248) Stack: (0xbf195ee8 to 0xbf196000) 5ee0: bf195f04 bf195ef8 8030b6fc 80308f38 bf195f44 bf195f08 5f00: 80166118 8030b6dc 8076ed30 bf14b000 bfbd8d80 00001000 bfbd8d88 bfbd8d80 5f20: 00001000 7e946c20 bf195f78 00000000 bf194000 00001000 bf195f74 bf195f48 5f40: 8010722c 80166084 801061e4 801118c0 00000000 00000000 bfbd8d80 7e946c20 5f60: 00000000 00001000 bf195fa4 bf195f78 8010741c 80107190 00000000 00000000 5f80: 00001000 7e946c20 00000003 00000003 8000ec88 00000000 00000000 bf195fa8 5fa0: 8000ea40 801073dc 00001000 7e946c20 00000003 7e946c20 00001000 00000000 5fc0: 00001000 7e946c20 00000003 00000003 00000001 00000001 00000001 00000003 5fe0: 00000000 7e946bfc 0001079d 76f5e1cc 40000010 00000003 00000000 00000000 [<80308f58>] (device_show_int+0x2c/0x38) from [<8030b6fc>] (drv_attr_show+0x2c/0x38) [<8030b6fc>] (drv_attr_show+0x2c/0x38) from [<80166118>] (sysfs_read_file+0xa0/0x144) [<80166118>] (sysfs_read_file+0xa0/0x144) from [<8010722c>] (vfs_read+0xa8/0x148) [<8010722c>] (vfs_read+0xa8/0x148) from [<8010741c>] (SyS_read+0x4c/0x80) [<8010741c>] (SyS_read+0x4c/0x80) from [<8000ea40>] (ret_fast_syscall+0x0/0x30) Code: e5913010 e1a0200c e3a01a01 e3482062 (e5933000) ---[ end trace 5cdf9dda0d86a7db ]--- Segmentation fault 

为什么我得到空引用?


编辑#1:

如果我用DEVICE_ATTR()replaceDEVICE_INT_ATTR()macros并提供我自己的show()store()函数,那么它工作正常。


编辑#2:

看来DEVICE_INT_ATTR()macros将var字段设置为NULL。 嗯….


编辑#3:当我用DEVICE_INT_ATTR()macros创buildstruct dev_ext_attribute结构时,我可以转储variables。 那是; 在我的探测函数中用printk()查看时,结构,函数指针和整数的地址都是正确的,但是当我的主函数show()函数查看结构时,结构是在不同的地址, var字段是NULL。

Solutions Collecting From Web of "如何为平台驱动程序正确初始化属性组?"

问题出现在这里分配attr_groups结构:

 static struct platform_driver platform = { .remove = my_remove, .probe = my_probe, .driver = { .name = DRIVER_NAME, .owner = THIS_MODULE, .groups = attr_groups, /* WRONGO: should not be assigned here. */ .of_match_table = of_match, }, }; 

通过在struct class ,一切都按预期工作:

 static int __init cz_tdm_init(void) { int ret; pr_info("MODNAME=%s", KBUILD_MODNAME); /* Dynamically allocate a major number and a * range of DEV_MINOR_NUMBER_COUNT (1) minor numbers. */ if ((ret = alloc_chrdev_region(&first, 0, DEV_MINOR_NUMBER_COUNT, DRIVER_NAME)) < 0) { ret = -ENODEV; goto exit; } /* Add the char device to the system. */ cdev_init(&cdev, &fops); if ((ret = cdev_add(&cdev, first, DEV_MINOR_NUMBER_COUNT)) < 0) { ret = -ENODEV; goto exit; } resources.cdev = 1; /* Create a class entry in sysfs */ if ((class = class_create(THIS_MODULE, "coveloz")) == NULL) { pr_err("Couldn't create 'struct class' structure."); ret = -ENODEV; goto exit; } class->dev_groups = attr_groups; /* RIGHTO */ /* Create the /dev/ file system entry */ /* return value ignored: there's a 'struct class' to 'struct device' mapping */ if (device_create(class, NULL, first, NULL, DRIVER_NAME) == NULL) { pr_err("Couldn't create entry in '/dev/' file system."); ret = -ENODEV; goto exit; }