seadragonzhl 发表于 2010-06-18 15:47

求助:块设备驱动程序

本帖最后由 seadragonzhl 于 2010-06-18 15:49 编辑

小弟新手,最近在学习块设备驱动。
但是下面的程序能编译通过,但是加载模块后就死机,请高手指点!
内核是linux-2.6.32.1。
代码如下:#include <linux/module.h>
#include <linux/init.h>
#include <linux/sched.h>
#include <linux/kernel.h>
#include <linux/fs.h>
#include <linux/types.h>
#include <linux/buffer_head.h>
#include <linux/blkdev.h>
#include <linux/msdos_fs.h>
#include <linux/fcntl.h>
#include <linux/delay.h>
#include <linux/elevator.h>

#define SIMP_BLKDEV_DEVICEMAJOR      COMPAQ_SMART2_MAJOR7
#define SIMP_BLKDEV_DISKNAME      "simp_blkdev"
#define SIMP_BLKDEV_BYTES      (16*1024*1024)

static struct request_queue *simp_blkdev_queue;
static struct gendisk *simp_blkdev_disk;
static void simp_blkdev_do_request(struct request_queue *q);
unsigned char simp_blkdev_data;

struct block_device_operations simp_blkdev_fops = {
    .owner                = THIS_MODULE,
};

static int __init simp_blkdev_init(void)
{
    int ret;
    simp_blkdev_queue = blk_init_queue(simp_blkdev_do_request, NULL);
    if (!simp_blkdev_queue) {
      ret = -ENOMEM;
      goto err_init_queue;
    }
    simp_blkdev_disk = alloc_disk(1);
    if (!simp_blkdev_disk) {
      ret = -ENOMEM;
      goto err_alloc_disk;
    }
    strcpy(simp_blkdev_disk->disk_name, SIMP_BLKDEV_DISKNAME);
    simp_blkdev_disk->major = SIMP_BLKDEV_DEVICEMAJOR;
    simp_blkdev_disk->first_minor = 0;
    simp_blkdev_disk->fops = &simp_blkdev_fops;
    simp_blkdev_disk->queue = simp_blkdev_queue;
    set_capacity(simp_blkdev_disk, SIMP_BLKDEV_BYTES>>9);
    add_disk(simp_blkdev_disk);
    return 0;

err_alloc_disk:
    blk_cleanup_queue(simp_blkdev_queue);

err_init_queue:
    return ret;
}

static void simp_blkdev_do_request(struct request_queue *q)
{
    struct request *req;
    //while ((req = elv_next_request(q)) != NULL) {
       while ((req = blk_fetch_request(q)) != NULL) {
      if ((blk_rq_pos(req) + blk_rq_cur_sectors(req)) << 9
             > SIMP_BLKDEV_BYTES) {
             printk(KERN_ERR SIMP_BLKDEV_DISKNAME
               ": bad request: block=%llu, count=%u\n",
               (unsigned long long)blk_rq_pos(req),
               blk_rq_cur_sectors(req));
             blk_end_request_cur(req, 0);
             continue;
      }
      switch (rq_data_dir(req)) {
    case READ:
             memcpy(req->buffer,
               simp_blkdev_data + (blk_rq_pos(req) << 9),
               blk_rq_cur_sectors(req) << 9);
             blk_end_request_cur(req, 1);
             break;
    case WRITE:
      memcpy(simp_blkdev_data + (blk_rq_pos(req) << 9),
             req->buffer, blk_rq_cur_sectors(req) << 9);
      blk_end_request_cur(req, 1);
      break;
    default:
      /* No default because rq_data_dir(req) is 1 bit */
      break;
    }
}
}

static void __exit simp_blkdev_exit(void)
{
    del_gendisk(simp_blkdev_disk);
    put_disk(simp_blkdev_disk);
    blk_cleanup_queue(simp_blkdev_queue);
}
module_init(simp_blkdev_init);
module_exit(simp_blkdev_exit);

jinxinxin163 发表于 2010-06-18 23:30

在可疑的代码处打印信息,既然死机,可能就无法执行dmesg命令了,那么你可以试一下这个:
用netconsole从网络上收集Kernel Panic信息详细方法
http://linux.chinaunix.net/bbs/thread-811116-1-225.html

seadragonzhl 发表于 2010-06-21 15:19

回复 2# jinxinxin163

多谢楼上,问题已经解决了,是一个函数用错了,谢谢!
但是我现在还是有个问题不太明白:我的这个模块使用insmod加载后,没有应用程序去调用它,但引用计数就成了1。这是为什么呢?
我用ps -e查看进程,果然多了一个blkid的进程,这个进程不知道是怎么来的?(模块名字叫blk)

jinxinxin163 发表于 2010-06-21 17:36

回复 3# seadragonzhl


    我觉的这个很有可能阿,因为说不定你上面调用的某个函数创建了一个内核线程

seadragonzhl 发表于 2010-06-23 15:11

回复 4# jinxinxin163


    嗯,问题暂时解决了,是__blk_end_request函数的问题,不过还不太清楚为什么整个系统会因为这个原因hang住。

chobit_s 发表于 2010-12-11 20:25

回复jinxinxin163


    嗯,问题暂时解决了,是__blk_end_request函数的问题,不过还不太清楚为什么 ...
seadragonzhl 发表于 2010-06-23 15:11 http://linux.chinaunix.net/bbs/images/common/back.gif
我写了个也hang个住了 进入blk_end_request就死机了!
这个到底是什么问题呢?

qccq 发表于 2010-12-24 11:59

      struct request *req;
        req = blk_fetch_request(q);
        while (req != NULL)
        {
                if (! blk_fs_request(req)) {
                        blk_end_request_all(req, -EIO);
                        continue;
                }
                switch(rq_data_dir(req))
                {
                case READ:
                                memcpy(req->buffer, blkdev_data + (blk_rq_pos(req) << 9), blk_rq_cur_sectors(req) << 9);
                                break;
                case WRITE:
                                memcpy(blkdev_data + (blk_rq_pos(req) << 9), req->buffer, blk_rq_cur_sectors(req) << 9);
                                break;
                }
                        if(!blk_end_request_cur(req, 0)) {
                        req = blk_fetch_request(q);
                }
        }在request函数里写成这样就行了

xjtuwjp 发表于 2010-12-28 11:21

源码分析版有个fujisu的大牛写的教你编写块设备驱动的文章,推荐你可以看看
页: [1]
查看完整版本: 求助:块设备驱动程序