小菜虎 发表于 2014-05-18 22:09

块设备驱动在add_disk的时候出问题了……

本帖最后由 小菜虎 于 2014-05-18 22:15 编辑

我编写的块设备驱动加载不上,经测试,程序卡在运行add_disk函数的时候。麻烦大大们帮我找下BUG谢谢{:3_194:} demsg日志和源代码如下:


MyBlk init done.
bop init done.
bdisk alloc done.
bdisk init done.
bqueue alloc done.
bqueue make request done.
Register blkdev done.
BUG: unable to handle kernel NULL pointer dereference at 0000021c
IP: [<c11305b0>] bdi_register+0x10/0x100
*pdpt = 0000000030d40001 *pde = 0000000000000000
Oops: 0000 [#1] SMP
Modules linked in: hello(OF+) bnep rfcomm bluetooth snd_hda_codec_hdmi x86_pkg_temp_thermal intel_powerclamp coretemp kvm_intel(F) kvm(F) crc32_pclmul(F) ppdev(F) eeepc_wmi asus_wmi sparse_keymap cdc_acm nouveau microcode(F) snd_hda_codec_realtek mxm_wmi ttm lpc_ich drm_kms_helper serio_raw(F) snd_hda_intel mei_me snd_hda_codec parport_pc(F) video(F) snd_hwdep(F) snd_pcm(F) drm snd_seq_midi(F) snd_seq_midi_event(F) snd_rawmidi(F) snd_page_alloc(F) snd_seq(F) snd_seq_device(F) snd_timer(F) i2c_algo_bit mei snd(F) wmi mac_hid soundcore(F) lp(F) parport(F) hid_generic usbhid hid r8169 mii(F)
CPU: 1 PID: 2404 Comm: insmod Tainted: GF          O 3.11.0-12-generic #19-Ubuntu
Hardware name: System manufacturer System Product Name/P8H61-M LX, BIOS 0601 08/31/2011
task: f1813380 ti: f0cec000 task.ti: f0cec000
EIP: 0060:[<c11305b0>] EFLAGS: 00010296 CPU: 1
EIP is at bdi_register+0x10/0x100
EAX: 000000d0 EBX: 000000d0 ECX: 00000000 EDX: 000000f8
ESI: f1b4fc5c EDI: 00000000 EBP: f0cedd8c ESP: f0cedd78
DS: 007b ES: 007b FS: 00d8 GS: 00e0 SS: 0068
CR0: 80050033 CR2: 0000021c CR3: 30d4e000 CR4: 000407f0
Stack:
00000330 00000015 00000001 f1b4fc00 f1b4fc5c f0cedda8 c11306d6 000000d0
00000000 c1871a1e 000000f8 00000000 f0cedde8 c12d9b8e 00000001 00000246
00000000 00000000 f1b4fc0c 00000001 0f800000 c1621d72 00000000 00000001
Call Trace:
[<c11306d6>] bdi_register_dev+0x36/0x40
[<c12d9b8e>] add_disk+0x11e/0x430
[<c1621d72>] ? printk+0x50/0x52
[<ff6ff000>] ? 0xff6fefff
[<ff6ff14f>] init_module+0x14f/0x1000
[<c10020ca>] do_one_initcall+0xca/0x190
[<ff6ff000>] ? 0xff6fefff
[<c104871f>] ? set_memory_nx+0x5f/0x70
[<c10b4a8e>] load_module+0x10ce/0x18d0
[<c10b531f>] SyS_init_module+0x8f/0xf0
[<c1632ccd>] sysenter_do_call+0x12/0x28
Code: 5d c3 c7 45 b8 00 00 00 00 e9 83 fe ff ff 8d b6 00 00 00 00 8d bc 27 00 00 00 00 55 89 e5 56 53 83 ec 0c 66 66 66 66 90 8b 5d 08 <8b> 83 4c 01 00 00 85 c0 74 0e 31 c0 83 c4 0c 5b 5e 5d c3 90 8d
EIP: [<c11305b0>] bdi_register+0x10/0x100 SS:ESP 0068:f0cedd78
CR2: 000000000000021c
---[ end trace 66605d80150e4d51 ]---

/*hello.c*/
#include <linux/init.h>
#include <linux/module.h>
#include <linux/fs.h>
#include <linux/blkdev.h>
#include <linux/genhd.h>
#include <linux/bio.h>
#include "myblk.h"

#define MYBLK_DEV_SIZE 200
#define MYBLK_DEV_MAJOR 248
#define MYBLK_DEV_NAME "MyBlkDev"

struct MyBlk *blk;
struct block_device_operations bop;
struct gendisk *bdisk;
struct request_queue *bqueue;

int open(struct inode *node, struct file *fp)
{
        return 0;
}

int release(struct inode *node, struct file *fp)
{
        return 0;
}

void myblk_make_request(struct request_queue *q, struct bio *bio)
{
        int i;
        char *buf;
        char *mem;
        struct bio_vec *bvl;
        if(((bio->bi_sector)<<9) + bio->bi_size > (MYBLK_DEV_SIZE<<9))
        {
                bio_io_error(bio);
                //return 0;
        }
        mem = blk->mem + ((bio->bi_sector)<<9);
        bio_for_each_segment(bvl, bio, i)
        {
                buf = __bio_kmap_atomic(bio,i/*,KM_USER0*/);
                switch(bio_data_dir(bio))
                {
                        case READ:
                        case READA:
                                memcpy(buf, mem, bvl->bv_len);
                                break;
                        case WRITE:
                                memcpy(mem, buf, bvl->bv_len);
                                break;
                        default:
                                break;
                }
                __bio_kunmap_atomic(buf/*, KM_USER0*/);
                mem += bvl->bv_len;
        }
        bio_endio(bio, /*bio->bi_size,*/ 0);
        //return 0;
}

int __init hello_init(void)
{
        blk = MyBlk_init(MYBLK_DEV_SIZE);
        if(blk == NULL)
        {
                printk(KERN_ALERT"Error init MyBlk.\n");
                return -1;
        }
        printk(KERN_ALERT"MyBlk init done.\n");
        //bop.open = open;
        //bop.release = release;
        bop.owner = THIS_MODULE;
        printk(KERN_ALERT"bop init done.\n");
        bdisk = alloc_disk(1);
        if(bdisk == NULL)
        {
                printk(KERN_ALERT"bdisk alloc error.\n");
                return -1;
        }
        printk(KERN_ALERT"bdisk alloc done.\n");
        bdisk->major = MYBLK_DEV_MAJOR;
        bdisk->first_minor = 0;
        bdisk->fops = &bop;
        set_capacity(bdisk, MYBLK_DEV_SIZE);
        strcpy(bdisk->disk_name, MYBLK_DEV_NAME);
        printk(KERN_ALERT"bdisk init done.\n");
        /*************************/
        bqueue = blk_alloc_queue(GFP_KERNEL);
        if(bqueue == NULL)
        {
                printk(KERN_ALERT"Error blk_alloc_queue\n");
                return -1;
        }
        printk(KERN_ALERT"bqueue alloc done.\n");
        blk_queue_make_request(bqueue, myblk_make_request);
        printk(KERN_ALERT"bqueue make request done.\n");
        //blk_queue_max_sectors(bqueue, MYBLK_DEV_SIZE);
        /*************************/
        if(0 > register_blkdev(MYBLK_DEV_MAJOR, MYBLK_DEV_NAME))
        {
                printk(KERN_ALERT"Register_blkdev error\n");
                return -1;
        }
        printk(KERN_ALERT"Register blkdev done.\n");
        add_disk(bdisk);
        printk(KERN_ALERT"Hello world!\n");
        return 0;
}
void __exit hello_exit(void)
{
        MyBlk_uninit(blk);
        blk_cleanup_queue(bqueue);
        del_gendisk(bdisk);
        unregister_blkdev(MYBLK_DEV_MAJOR, MYBLK_DEV_NAME);
        printk(KERN_ALERT"Goodbye world!\n");
}

module_init(hello_init);
module_exit(hello_exit);

MODULE_LICENSE("Dual BSD/GPL");
MODULE_AUTHOR("Xiaocaihu");
MODULE_VERSION("1.0");

/*myblk.h*/
#include <linux/slab.h>
struct MyBlk
{
        char* mem;
        sector_t size;
};

struct MyBlk* MyBlk_init(sector_t size)
{
        struct MyBlk *blk;
        blk = kmalloc(sizeof(struct MyBlk), GFP_KERNEL);
        if(blk == NULL)
        {
                printk(KERN_ALERT"blk alloc error!\n");
                return NULL;
        }
        blk->size = size;
        blk->mem = kmalloc(size<<9, GFP_KERNEL);
        if(blk->mem == NULL)
        {
                printk(KERN_ALERT"Mem alloc error!\n");
                kfree(blk);
                return NULL;
        }
        return blk;
}

void MyBlk_uninit(struct MyBlk *blk)
{
        if(blk && blk->mem)
                kfree(blk->mem);
        if(blk)
                kfree(blk);
}

humjb_1983 发表于 2014-05-19 08:42

非法地址访问,需要反汇编看看具体出错的代码行和具体变量,确认变量的来源,看看是不是你传入的参数有问题。

小菜虎 发表于 2014-05-19 23:52

回复 2# humjb_1983


    谢谢你的回复,可我还是不知道问题出在哪儿……

小菜虎 发表于 2014-05-20 00:41

本帖最后由 小菜虎 于 2014-05-20 00:42 编辑

回复 2# humjb_1983


    找到问题了。我忘了把请求队列赋值给gendisk,低级失误啊{:3_204:}

在hello.c文件的第99行和第100行之间插入代码:
bdisk->queue = bqueue;
问题解决{:3_200:}

再次感谢你的回复:mrgreen:

humjb_1983 发表于 2014-05-20 08:42

呵呵,找到问题就好,此类问题通常是自己编写的代码所致,内核中稍不留神就这样~,坑踩多了就好了
页: [1]
查看完整版本: 块设备驱动在add_disk的时候出问题了……