[国嵌攻略][147][简单块设备驱动设计]
头文件
#include <linux/blkdev.h>
#include <linux/bio.h>
blkdev.c
/******************************************************************** *头文件 *********************************************************************/ #include <linux/init.h> #include <linux/module.h> #include <linux/errno.h> #include <linux/blkdev.h> #include <linux/bio.h> #include <linux/vmalloc.h> /******************************************************************** *类型定义 *********************************************************************/ typedef struct blkdev{ int size; //数据大小 char *data; //数据内容 struct request_queue *queue; //请求队列 struct gendisk *gd; //磁盘结构 }BLKDEV; /******************************************************************** *全局变量 *********************************************************************/ static int major; //主设备号 BLKDEV *blkDev; //设备结构 /******************************************************************** *请求队列 *********************************************************************/ //处理请求 void blk_transfer(BLKDEV *blkDev, unsigned long sector,unsigned long number, char *buffer, int direction){ //计算扇区位置 unsigned long offset, nbytes; offset = sector * 512; //设置扇区位置 nbytes = number * 512; //设置扇区大小 //处理操作请求 if(direction){ //是否写入请求 memcpy(blkDev->data + offset, buffer, nbytes); //向扇区写数据 }else{ //是否读取请求 memcpy(buffer, blkDev->data + offset, nbytes); //从扇区读数据 } } //处理队列 void blk_request_queue(struct request_queue *q){ //获取队列请求 struct request *req; int isEnd; req = blk_fetch_request(q); while(req != NULL){ //是否存在请求 //处理队列请求 blk_transfer(blkDev, blk_rq_pos(req), blk_rq_cur_sectors(req), req->buffer, rq_data_dir(req)); //获取队列请求 isEnd = __blk_end_request_cur(req, 0); if(!isEnd){ //是否不是最后请求 req = blk_fetch_request(q); } } } /******************************************************************** *设备方法 *********************************************************************/ struct block_device_operations blk_ops = { .owner = THIS_MODULE }; /******************************************************************** *模块安装 *********************************************************************/ //安装模块 static int iblk_init(void){ //注册设备结构 major = register_blkdev(0, "iblk"); //动态分配主设备号 if(major <= 0){ //如果分配失败返回 printk("Register block device fail!\n"); return -EBUSY; } //分配设备结构 blkDev = kmalloc(sizeof(BLKDEV), GFP_KERNEL); //分配设备空间 blkDev->size = 1024 * 512; //扇区大小=扇区数量*每块大小 blkDev->data = vmalloc(blkDev->size); //分配请求队列 blkDev->queue = blk_init_queue(blk_request_queue, NULL); //设置队列扇区 blk_queue_logical_block_size(blkDev->queue, 512); //分配磁盘结构 blkDev->gd = alloc_disk(1); //设置磁盘结构 blkDev->gd->major = major; //主设备号 blkDev->gd->first_minor = 0; //起始次设备号 blkDev->gd->fops = &blk_ops; //设备方法 blkDev->gd->queue = blkDev->queue; //请求队列 blkDev->gd->private_data = blkDev; //私有成员 sprintf(blkDev->gd->disk_name, "iblk%d", 0); //设备文件名称 set_capacity(blkDev->gd, 1024); //扇区数量 add_disk(blkDev->gd); //设置磁盘结构 return 0; } //卸载模块 static void iblk_exit(void){ //释放磁盘结构 del_gendisk(blkDev->gd); //释放请求队列 blk_cleanup_queue(blkDev->queue); //释放结构空间 vfree(blkDev->data); //释放设备结构 kfree(blkDev); //注销设备结构 unregister_blkdev(major, "iblk"); } /******************************************************************** *模块声明 *********************************************************************/ MODULE_LICENSE("GPL"); MODULE_AUTHOR("D"); MODULE_DESCRIPTION(""); MODULE_VERSION("v1.0"); module_init(iblk_init); module_exit(iblk_exit);
Makefile
ifneq ($(KERNELRELEASE),) obj-m := blkdev.o else KDIR := /lib/modules/2.6.32-279.el6.i686/build all: make -C $(KDIR) M=$(PWD) modules clean: @rm -f *.ko *.ko.unsigned *.mod.c *.mod.o *.o *.order *.symvers endif