2014-07-07 50 views
3

編輯#4: 我想通了,我不應該在struct platform_driver結構的driver場被分配attr_groupsgroups領域。請在下面查看評論/* WRONGO: should not be assigned here. */如何爲平臺驅動程序正確初始化屬性組?

我還沒有想出,我應該尚未被分配給它...


我一個平臺驅動程序代碼管理,以使內核「OOPS」看書,因爲sysfs屬性時一個NULL引用。我敢肯定,這是下面的代碼一個簡單的疏忽,但我不能看到它:

... 

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: 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_INT_ATTR()宏觀與DEVICE_ATTR()並提供我自己的show() & store()功能,它工作正常。


EDIT#2:

它出現DEVICE_INT_ATTR()宏設置的var字段爲NULL。嗯....


編輯#3: 當我創建struct dev_ext_attribute結構DEVICE_INT_ATTR()宏,我可以轉儲的變量。那是;在我的探測函數中用printk()查看時,結構,函數指針和我試圖在sysfs中公開的整數地址都是正確的,但是當我的主函數看到結構時,結構是一個不同的地址和var字段是NULL。

+0

我想這說明了我的錯誤的原因:HTTP ://stackoverflow.com/q/24621955/32836 – Jamie

回答

1

問題從這裏分配attr_groups結構出現了:通過struct class而不是做它

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, 
    }, 
}; 

,一切正常:

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; 
    }