加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 综合聚焦 > 服务器 > Linux > 正文

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

发布时间:2020-12-13 23:25:48 所属栏目:Linux 来源:网络整理
导读:编辑#4: 我发现我不应该将attr_groups分配给struct platform_driver结构的驱动程序字段中的groups字段.寻找评论/ * WRONGO:不应该在这里分配. * /下面. 我还没弄明白我应该把它分配到哪里…… 由于NULL引用,我的平台驱动程序代码在读取sysfs属性时会导致内
编辑#4:
我发现我不应该将attr_groups分配给struct platform_driver结构的驱动程序字段中的groups字段.寻找评论/ * WRONGO:不应该在这里分配. * /下面.

我还没弄明白我应该把它分配到哪里……

由于NULL引用,我的平台驱动程序代码在读取sysfs属性时会导致内核“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,};

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: G           O 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()替换DEVICE_INT_ATTR()宏并提供我自己的show()& store()函数,它工作正常.

编辑#2:

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

编辑#3:
当我使用DEVICE_INT_ATTR()宏创建struct dev_ext_attribute结构时,我可以转储变量.那是;我在探测函数中使用printk()查看结构的地址,函数指针和我试图在sysfs中公开的整数的地址都是正确的,但是当我的home spun show()函数查看结构时,struture位于不同的地址,var字段为NULL.

解决方法

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

static struct platform_driver platform = {
    .remove = my_remove,};

通过在struct类中执行它,一切都按预期工作:

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,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,DRIVER_NAME) == NULL) {
        pr_err("Couldn't create entry in '/dev/' file system.");
        ret = -ENODEV;
        goto exit;
    }

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读