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");
块设备驱动程序2
最新推荐文章于 2022-07-01 21:56:36 发布