主题 : cat查看设备属性文件时内核崩溃,帮忙看一下这个oops~ 复制链接 | 浏览器收藏 | 打印
级别: 新手上路
UID: 51637
精华: 0
发帖: 40
金钱: 205 两
威望: 41 点
综合积分: 80 分
注册时间: 2011-07-05
最后登录: 2015-10-08
楼主  发表于: 2012-01-20 19:40

 cat查看设备属性文件时内核崩溃,帮忙看一下这个oops~

oops信息:
/sys/devices/my_bus0/my_dev # cat dev
/sys/devices/my_bus0/my_dev # cat dev
Unable to handle kernel paging request at virtual address 6420796c
pgd = ccc4c000
[6420796c] *pgd=00000000
Internal error: Oops: 80000005 [#1] PREEMPT
last sysfs file: /sys/devices/my_bus0/my_dev/dev
Modules linked in: device bus
CPU: 0    Not tainted  (2.6.38-FriendlyARM #2)
PC is at 0x6420796c
LR is at dev_attr_show+0x20/0x44
pc : [<6420796c>]    lr : [<c01d5030>]    psr: 20000033
sp : ccc45f18  ip : 00000000  fp : be8a3cb8
r10: 00000fff  r9 : cd7f8138  r8 : ccc45f80
r7 : c0417454  r6 : ccc3e240  r5 : bf006170  r4 : bf0060a0
r3 : 6420796d  r2 : ccc1d000  r1 : bf006170  r0 : bf006098
Flags: nzCv  IRQs on  FIQs on  Mode SVC_32  ISA Thumb  Segment user
Control: 00c5387d  Table: 5cc4c008  DAC: 00000015
Process cat (pid: 930, stack limit = 0xccc44268)
Stack: (0xccc45f18 to 0xccc46000)
5f00:                                                       bf0060a0 cd7f8120
5f20: ccc3e240 c00ed0d0 00000021 00212000 00000001 00001000 ccc45f4c cd40caa0
5f40: 00001000 be8a3cb8 ccc45f80 00001000 ccc44000 00000000 00000000 c00a530c
5f60: cd40caa0 be8a3cb8 00000000 00000000 cd40caa0 be8a3cb8 00001000 c00a5440
5f80: 00000000 00000000 00001000 00000000 00001000 be8a3cb8 00000003 00000003
5fa0: c0034f88 c0034de0 00001000 be8a3cb8 00000003 be8a3cb8 00001000 001eeea8
5fc0: 00001000 be8a3cb8 00000003 00000003 00000000 00000001 00000001 00000000
5fe0: 001f04c0 be8a3c98 0001b5dc 00008e2c 60000010 00000003 00000000 00000000
[<c01d5030>] (dev_attr_show+0x20/0x44) from [<c00ed0d0>] (sysfs_read_file+0xb8/0
x130)
[<c00ed0d0>] (sysfs_read_file+0xb8/0x130) from [<c00a530c>] (vfs_read+0xac/0x134
)
[<c00a530c>] (vfs_read+0xac/0x134) from [<c00a5440>] (sys_read+0x3c/0x68)
[<c00a5440>] (sys_read+0x3c/0x68) from [<c0034de0>] (ret_fast_syscall+0x0/0x30)
Code: bad PC value
---[ end trace ec3caf42aca4e3ae ]---
one_wire_status: 2
Segmentation fault
/sys/devices/my_bus0/my_dev #


加载模块后第一次cat dev什么都没显示,再cat一次内核崩溃~
而创建的总线属性文件却可以正常cat:
/sys/bus/my_bus # cat version
$Revision: 1.9 $


objdump了一下出错时LR指向的dev_attr_show+0x20/0x44地方,为904位置:
    struct device_attribute *dev_attr = to_dev_attr(attr);
    struct device *dev = to_dev(kobj);
     8fc:    e2400008     sub    r0, r0, #8    ; 0x8
     900:    e12fff33     blx    r3
    ssize_t ret = -EIO;

    if (dev_attr->show)
        ret = dev_attr->show(dev, dev_attr, buf);
    if (ret >= (ssize_t)PAGE_SIZE) {
     904:    e3500a01     cmp    r0, #4096    ; 0x1000
级别: 新手上路
UID: 51637
精华: 0
发帖: 40
金钱: 205 两
威望: 41 点
综合积分: 80 分
注册时间: 2011-07-05
最后登录: 2015-10-08
1楼  发表于: 2012-01-20 19:43
模块代码:bus.c:
#include <linux/device.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/string.h>

MODULE_AUTHOR("David Xie");
MODULE_LICENSE("Dual BSD/GPL");

static char *Version = "$Revision: 1.9 $";

static int my_match(struct device *dev, struct device_driver *driver)
{
    return !strncmp(dev_name(dev), driver->name, strlen(driver->name));
}

static void my_bus_release(struct device *dev)
{
    printk(KERN_DEBUG "my bus release\n");
}
    
struct device my_bus = {
    .release  = my_bus_release
};


struct bus_type my_bus_type = {
    .name = "my_bus",
    .match = my_match,
};

EXPORT_SYMBOL(my_bus);
EXPORT_SYMBOL(my_bus_type);


/*
* Export a simple attribute.
*/
static ssize_t show_bus_version(struct bus_type *bus, char *buf)
{
    return snprintf(buf, PAGE_SIZE, "%s\n", Version);
}

static BUS_ATTR(version, S_IRUGO, show_bus_version, NULL);


static int __init my_bus_init(void)
{
    int ret;
        
        /*注册总线*/
    ret = bus_register(&my_bus_type);
    if (ret)
        return ret;
        
    /*创建属性文件*/    
    if (bus_create_file(&my_bus_type, &bus_attr_version))
        printk(KERN_NOTICE "Fail to create version attribute!\n");
    
    /*注册总线设备*/
    dev_set_name(&my_bus,"my_bus0");
    ret = device_register(&my_bus);
    if (ret)
        printk(KERN_NOTICE "Fail to register device:my_bus!\n");
        
    return ret;
}

static void my_bus_exit(void)
{
    device_unregister(&my_bus);
    bus_unregister(&my_bus_type);
}

module_init(my_bus_init);
module_exit(my_bus_exit);


device.c:
#include <linux/device.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/string.h>

MODULE_AUTHOR("David Xie");
MODULE_LICENSE("Dual BSD/GPL");

extern struct device my_bus;
extern struct bus_type my_bus_type;

/* Why need this ?*/
static void my_dev_release(struct device *dev)
{
    
}

struct device my_dev = {
    .bus = &my_bus_type,
    .parent = &my_bus,
    .release = my_dev_release,
};

/*
* Export a simple attribute.
*/
static ssize_t mydev_show(struct device *dev, char *buf)
{
    return snprintf(buf, PAGE_SIZE, "%s\n", "This is my device!");
}

static DEVICE_ATTR(dev, S_IRUGO, mydev_show, NULL);

static int __init my_device_init(void)
{
    int ret = 0;
        
        /* 初始化设备 */
    dev_set_name(&my_dev,"my_dev");
        
        /*注册设备*/
    device_register(&my_dev);
        
    /*创建属性文件*/
    device_create_file(&my_dev, &dev_attr_dev);
    
    return ret;    

}

static void my_device_exit(void)
{
    device_unregister(&my_dev);
}

module_init(my_device_init);
module_exit(my_device_exit);