Chinaunix首页 | 论坛 | 博客
  • 博客访问: 145350
  • 博文数量: 58
  • 博客积分: 130
  • 博客等级: 入伍新兵
  • 技术积分: 310
  • 用 户 组: 普通用户
  • 注册时间: 2011-11-19 21:38
文章分类
文章存档

2012年(22)

2011年(36)

分类:

2011-12-14 00:30:41

 block.rar    写一个块设备驱动--没看过的可以看看(完整).doc   

实验源文件

 

/******************************************************

*authortingkman

*time  2011.12.9

*ver   v1
*******************************************************/

一、试验环境:

虚拟机:vmware

系统:red hat enterprise 6

版本:2.6.32

交叉编译链:内核自带gcc 版本 4.4.4 20100726 (Red Hat 4.4.4-13) (GCC)

/********************************************************

模块文件:Mod.c

********************************************************

#include //模块函数定义处

#include //通用设备函数定义处

#include //COMPAQ定义处

#include //request_queue 定义处 建议自己查看

#include

#include

#define SIMP_BLKDEV_DISKNAME "simp_blkdev"

#define SIMP_BLKDEV_DEVICEMAJOR COMPAQ_SMART2_MAJOR

#define SIMP_BLKDEV_BYTES (16*1024*1024)

unsigned char simp_blkdev_data[SIMP_BLKDEV_BYTES];

static struct gendisk *simp_blkdev_disk;

static struct request_queue *simp_blkdev_queue;//定义一个request_queue结构体指针

int ret;

static void simp_blkdev_do_request(struct request_queue *q)

{

              struct request *req;

              /*电梯调度算法实现*/

        while ((req = elv_next_request(q)) != NULL) {

                if ((req->sector + req->current_nr_sectors) << 9

                        > SIMP_BLKDEV_BYTES) {

                        printk(KERN_ERR SIMP_BLKDEV_DISKNAME

                                ": bad request: block=%llu, count=%u\n",

                                (unsigned long long)req->sector,

                                req->current_nr_sectors);

                        end_request(req, 0);

                        continue;

                }

                            /*判断是读还是写数据*/

                switch (rq_data_dir(req)) {

                case READ:

                                   /*因为是在内存李的块设备,数据操作知识memcpy,实际设备合作和这不一样*/

                        memcpy(req->buffer,

                                simp_blkdev_data + (req->sector << 9),

                                req->current_nr_sectors << 9);

                        end_request(req, 1);

                        break;

                case WRITE:

                        memcpy(simp_blkdev_data + (req->sector << 9),

                                req->buffer, req->current_nr_sectors << 9);

                        end_request(req, 1);

                        break;

                default:

                        /* No default because rq_data_dir(req) is 1 bit */

                        break;

                }

        }

 

}

struct block_device_operations simp_blkdev_fops={

       .owner =THIS_MODULE,//此处为逗号,结尾为分号

};

static int __init simp_blkdev_init(void)

{

       int ret;

       /*初始化话请求队列这里I/O调度算法是默认的blk_init_queue()即楼梯调度算法*/

       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)//申请成功返回1否则返回0

              {

                     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);//设置块容量,以扇区为单位一个扇区512byte

       /*添加设备*/

       add_disk(simp_blkdev_disk);//入口处添加设备

      return 0;

       err_alloc_disk:

              return ret;

       err_init_queue:

              return ret;

}

static void __exit simp_blkdev_exit(void)

{

       /*注意次序,先申请请求队列,然后申请资源,然后添加设备*/

       del_gendisk(simp_blkdev_disk);//这个地方为什么不是邋del_disk查看内核就是这么定义的、出口处删除设备,添加-删除成对出现

       put_disk(simp_blkdev_disk);//出口处释放资源,申请和释放成对出现

       blk_cleanup_queue(simp_blkdev_queue);//

}

module_init(simp_blkdev_init);

module_exit(simp_blkdev_exit);

 

MODULE_LICENSE ("GPL");

MODULE_AUTHOR("tingkman");

MODULE_DESCRIPTION("For test");

*******************************************************************************Makefile

obj-m :=mod.o

#KDIR :=/home/yao/driver/block/linux-2.6.32

#KDIR :=/home/yao/kernel_apollo_pro_hdnp

KDIR := /lib/modules/$(shell uname -r)/build

PWD :=$(shell pwd)

default:

       $(MAKE) -C $(KDIR) SUBDIRS=$(PWD) modules

clean:

       $(MAKE) -C $(KDIR) SUBDIRS=$(PWD) clean

       rm -rf Module.markers modules.order Module.symvers

注意到KDIR 指向内核目录,因为编译模块依赖内核

执行Make命令

[root@localhost block]# make

make -C /lib/modules/2.6.32-71.el6.i686/build SUBDIRS=/home/yao/driver/block modules

make[1]: Entering directory `/usr/src/kernels/2.6.32-71.el6.i686'

  CC [M]  /home/yao/driver/block/mod.o

/home/yao/driver/block/mod.c: 在函数‘simp_blkdev_do_request’中:

/home/yao/driver/block/mod.c:18: 错误:隐式声明函数‘elv_next_request

/home/yao/driver/block/mod.c:18: 警告:赋值时将整数赋给指针,未作类型转换

/home/yao/driver/block/mod.c:19: 错误:‘struct request’没有名为‘sector’的成员

/home/yao/driver/block/mod.c:19: 错误:‘struct request’没有名为‘current_nr_sectors’的成员

/home/yao/driver/block/mod.c:23: 错误:‘struct request’没有名为‘sector’的成员

/home/yao/driver/block/mod.c:24: 错误:‘struct request’没有名为‘current_nr_sectors’的成员

/home/yao/driver/block/mod.c:25: 错误:隐式声明函数‘end_request

/home/yao/driver/block/mod.c:32: 错误:‘struct request’没有名为‘sector’的成员

/home/yao/driver/block/mod.c:32: 错误:‘struct request’没有名为‘current_nr_sectors’的成员

/home/yao/driver/block/mod.c:38: 错误:‘struct request’没有名为‘sector’的成员

/home/yao/driver/block/mod.c:38: 错误:‘struct request’没有名为‘current_nr_sectors’的成员

make[2]: *** [/home/yao/driver/block/mod.o] 错误 1

make[1]: *** [_module_/home/yao/driver/block] 错误 2

make[1]: Leaving directory `/usr/src/kernels/2.6.32-71.el6.i686'

make: *** [default] 错误 2

[root@localhost block]#

出错,出错原因理解为函数elv_next_requestsectorcurrent_nr_sectors等找不到,刚开始以为头文件没找到,因为elv_next_request函数在#include 文件中包含,但是查了一下确实包含,为什么会找不到那,不理解,怀疑是不是kernel路径不对,于是将KDIR := /lib/modules/$(shell uname -r)/build改成KDIR :=/home/yao/kernel_apollo_pro_hdnp这是我一个开发板上的内核路径,然后make

make -C /home/yao/kernel_apollo_pro_hdnp SUBDIRS=/home/yao/driver/block modules

make[1]: Entering directory `/home/yao/kernel_apollo_pro_hdnp'

  CC [M]  /home/yao/driver/block/mod.o

  Building modules, stage 2.

  MODPOST 1 modules

  CC      /home/yao/driver/block/mod.mod.o

  LD [M]  /home/yao/driver/block/mod.ko

make[1]: Leaving directory `/home/yao/kernel_apollo_pro_hdnp'

编译通过,首先声明一下,该内核版本是2.6.27,,为什么会这样,我也不知道,于是将mod.ko下到开发板加载,insmod有出错了,说没有足够的内存,郁闷了,可能是开发板的内存太小,不适合这个基于内存的驱动,想一下还是在虚拟机里面做,于是有google一下,有人说内核版本问题新的内核没有elv_next_request这个函数了,,这是后我想起来,是不是我的内核版本太高了,于是,我吧编译环境改成red hat enterprise 5 该内核是2.6.18,编译通过,看来是内核版本问题,这也是为什么我要在前面写开发环境的原因。

 

该编译虽然通过,但是格式化时有些问题,以后研究

阅读(1040) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~