块设备驱动程序2

10 篇文章 0 订阅
 1	#include <linux/init.h>
 2	#include <linux/kernel.h>
 3	#include <linux/module.h>
 4	
 5	#include <linux/fs.h>
 6	#include <linux/slab.h>
 7	#include <linux/genhd.h>
 8	#include <linux/blkdev.h>
 9	#include <linux/hdreg.h>
 10	#include <linux/vmalloc.h>
 11	
 12	#define VDSK_MINORS 4
 13	#define VDSK_HEADS 4
 14	#define VDSK_SECTORS 16
 15	#define VDSK_CYLINDERS 256
 16	#define VDSK_SECTOR_SIZE 512
 17	#define VDSK_SECTOR_TOTAL (VDSK_HEADS * VDSK_SECTORS * VDSK_CYLINDERS)
 18	#define VDSK_SIZE (VDSK_SECTOR_SIZE * VDSK_SECTOR_TOTAL)
 19	 
 20	static int vdsk_major = 0;
 21	static char vdsk_name[] = "vdsk";
 22	struct vdsk_dev{
 23	    u8 *data;
 24	    int size;                                                                                                                              
 25	    spinlock_t lock;
 26	    struct gendisk *gd;
 27	    struct request_queue *queue;
 28	};
 29	
 30	struct vdsk_dev *vdsk = NULL;
 31	
 32	static int vdsk_open(struct block_device *bdev, fmode_t mode){
 33	    return 0;
 34	}
 35	static int vdsk_release(struct gendisk *gd, fmode_t mode){
 36	    return 0;
 37	}
 38	 
 39	static int vdsk_ioctl(struct block_device *bdev, fmode_t mode, unsigned cmd, unsigned long arg){
 40	    return 0;                                                                                                                              
 41	}
 42	/*获取虚拟磁盘的几何数据*/
 43	static int vdsk_getgeo(struct block_device *bdev, struct hd_geometry *geo){
 44	    geo->cylinders = VDSK_CYLINDERS;
 45	    geo->heads = VDSK_HEADS;
 46	    geo->sectors = VDSK_SECTORS;
 47	    geo->start = 0;
 48	    return 0;
 49	}
 50	
 51	/*快设备操作方法集合*/
 52	static struct block_device_operations vdsk_fops = {
 53	    .owner = THIS_MODULE,
 54	    .open = vdsk_open,
 55	    .release = vdsk_release,
 56	    .ioctl = vdsk_ioctl,
 57	    .getgeo = vdsk_getgeo,
 58	};
 59	/*构造请求的函数*/
 60	static void vdsk_request(struct request_queue *q){                                                                                         
 61	    struct vdsk_dev *vdsk;
 62	    struct request *req;
 63	    struct bio *bio;
 64	    struct bio_vec *bvec;
 65	    unsigned long offset;
 66	    unsigned long nbytes;
 67	    char *buffer;
 68	
 69	    vdsk = q->queuedata;
 70	    /*取出队列中最顶端的请求*/
 71	    req = blk_fetch_request(q);
 72	
 73	    while(req != NULL){
 74	        /*从请求中取出每一个bio*/
 75	        __rq_for_each_bio(bio, req){
 76	            /*从每一个bio中取出每一个bio_vec*/
 77	            bio_for_each_segment(bvec, bio, bio->bi_vcnt){
 78	                /*映射缓存区地址*/
 79	                buffer = __bio_kmap_atomic(bio, bio->bi_idx, 0);
 80	                /*要访问的磁盘的起始地址,单位为字节*/
 81	                offset = bio->bi_sector * VDSK_SECTOR_SIZE;
 82	                /*访问的字节数*/
 83	                nbytes = bvec->bv_len;
 84	
 85	                /*如果访问的数据容量大于块设备的总容量,则访问出错*/
 86	                if((offset + nbytes) > get_capacity(vdsk->gd) * VDSK_SECTOR_SIZE){
 87	                    bio_endio(bio, -EINVAL);
 88	                    return ;
 89	                }
 90	
 91	                /*如果为写设备操作*/
 92	                if(bio_data_dir(bio) == WRITE){
 93	                    /*将缓存区中的数据复制到块设备对应的扇区中*/
 94	                    memcpy(vdsk->data + offset, buffer, nbytes);
 95	                }                                                                                                                          
 96	                else{
 97	                    /*如果为读操作,则将块设备对应的扇区中的数据复制到缓存区中*/
 98	                    memcpy(buffer, vdsk->data + offset, nbytes);
 99	                }
 100                 /*操作完成,解除缓存区的地址映射关系*/
 101                 __bio_kunmap_atomic(buffer, 0);
 102             }
 103         }
 104         /*完成请求并更新请求*/
 105         if(!__blk_end_request_cur(req, 0)){
 106             req = blk_fetch_request(q);
 107         }
 108     }
 109 }
 110 /*加载函数*/
 111 static int __init vdsk_test_init(void)                                                                                                     
 112 {
 113     printk(KERN_INFO"--------%s--------\n", __func__);
 114     /*注册设备号*/
 115     vdsk_major = register_blkdev(vdsk_major, vdsk_name);
 116     if(vdsk_name <= 0){
 117         return -EBUSY;
 118     }
 119     /*为自定义结构体申请内存空间*/
 120     vdsk = kzalloc(sizeof(struct vdsk_dev), GFP_KERNEL);
 121     if(!vdsk){
 122         goto unreg_dev;
 123     }
 124     /*磁盘容量*/
 125     vdsk->size = VDSK_SIZE;
 126     /*申请内存模拟块设备*/
 127     vdsk->data = vmalloc(vdsk->size);
 128     if(!vdsk->data){
 129         goto free_dev;
 130     }
 131 
 132     /*申请分配一个请求队列并初始化,指定请求处理函数vdsk_request*/                                                                          
 133     spin_lock_init(&vdsk->lock);
 134     vdsk->queue = blk_init_queue(vdsk_request, &vdsk->lock);
 135 
 136     /*设置逻辑扇区的大小为512字节*/
 137     blk_queue_logical_block_size(vdsk->queue, VDSK_SECTOR_SIZE);
 138     vdsk->queue->queuedata = vdsk;
 139 
 140     /*申请分配gendisk结构对象*/
 141     vdsk->gd = alloc_disk(VDSK_MINORS);
 142     if(!vdsk->gd){
 143         goto free_data;
 144     }
 145     /*初始化gendisk结构对象*/
 146     vdsk->gd->major = vdsk_major;  /*赋值注册的块设备设备号*/
 147     vdsk->gd->first_minor = 0;
 148     vdsk->gd->fops = &vdsk_fops;   /*设置操作方法集合*/
 149     vdsk->gd->queue = vdsk->queue; /*赋值请求队列*/
 150     vdsk->gd->private_data = vdsk;
 151     /*设置块设备名称*/
 152     snprintf(vdsk->gd->disk_name, 32, "vdsk%c", 'a');
 153     /*设置磁盘容量*/                                                                                                                       
 154     set_capacity(vdsk->gd, VDSK_SECTOR_TOTAL);
 155     /*添加gendisk结构对象到内核中*/
 156     add_disk(vdsk->gd);
 157 
 158     return 0;
 159 
 160 free_data:
 161     blk_cleanup_queue(vdsk->queue);
 162     vfree(vdsk->data);
 163 free_dev:
 164     kfree(vdsk);
 165 unreg_dev:
 166     unregister_blkdev(vdsk_major, vdsk_name);
 167     return -ENOMEM;
 168 }
 169 /*卸载函数*/
 170 static void __exit vdsk_test_exit(void)
 171 {
 172     printk(KERN_INFO"--------%s--------\n", __func__);
 173     del_gendisk(vdsk->gd);
 174     put_disk(vdsk->gd);
 175     blk_cleanup_queue(vdsk->queue);
 176     vfree(vdsk->data);
 177     kfree(vdsk);
 178     unregister_blkdev(vdsk_major, vdsk_name);
 179 
 180     return ;
 181 }
 182 
 183 module_init(vdsk_test_init);                                                                                                               
 184 module_exit(vdsk_test_exit);
 185 
 186 MODULE_LICENSE("GPL");
 187 MODULE_AUTHOR("qianfeng <www.mobiletrain.org>");
 188 MODULE_DESCRIPTION("blk_test_dev driver");

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值