实验七补充sbull虚拟的磁盘驱动的编写.docx
- 文档编号:8045563
- 上传时间:2023-01-28
- 格式:DOCX
- 页数:19
- 大小:22.89KB
实验七补充sbull虚拟的磁盘驱动的编写.docx
《实验七补充sbull虚拟的磁盘驱动的编写.docx》由会员分享,可在线阅读,更多相关《实验七补充sbull虚拟的磁盘驱动的编写.docx(19页珍藏版)》请在冰豆网上搜索。
实验七补充sbull虚拟的磁盘驱动的编写
sbull虚拟的磁盘驱动的编写
分类:
Embedded[ARM/DSP...]驱动2011-11-2817:
24191人阅读评论(0)收藏举报
原理指导:
我们通过vmalloc在内存中开辟一部分空间,作为一个虚拟的磁盘,然后我们以块设备的方式来访问这片内存,例如这个sbull模型。
sbull(Simple Block Utility for Loading Localities),该驱动程序实现了一个使用系统内存的块设备,从本质上讲,属于一种 RAM 磁盘驱动程序。
字符设备的IO操作则是直接不绕弯的,块设备的IO操作会配对和整合。
驱动的任务是处理请求,对于这些请求的排队和整合的工作有IO调度算法处理。
所以块设备的核心工作就是:
请求处理函数或者是制造请求。
Block_devices_operations结构体中没有读写一类的成员函数,而只是包含打开、释放和IO控制等函数。
块设备的流程:
(1)先把模块模型搭建好
MODULE_LICENSE("Dual BSD/GPL");
static struct block_device_operations sbull_ops = {
.owner = THIS_MODULE,
.open = sbull_open,
.release = sbull_release,
.media_changed = sbull_media_changed,
.revalidate_disk = sbull_revalidate,
.ioctl = sbull_ioctl,
.getgeo= sbull_getgeo,
};
module_init(sbull_init);
module_exit(sbull_exit);
(2)定义一个我们用内存虚拟出来的块设备sbull_dev
struct sbull_dev {
int size; /* Device size in sectors */
u8 *data; /* The data array */
short users; /* How many users */
short media_change; /* Flag a media change?
*/
spinlock_t lock; /* For mutual exclusion */
struct request_queue *queue; /* The device request queue */
struct gendisk *gd; /* The gendisk structure */
struct timer_list timer; /* For simulated media changes */
};
这个设备结构体是我们工作的核心,也许你不知道需要哪些成员,不要紧,还是那句话,编写驱动的时候,需要设备表现出那些性质和功能,相应的添加上就OK了。
(3)设备的初始化
sbull_init( ){
一、sbull_major = register_blkdev(sbull_major, "sbull");
二、Static struct sbull_dev *Devices = kmalloc(ndevices*sizeof (struct sbull_dev), GFP_KERNEL);//在这里可以对Kmalloc的结果判断下,然后进一步处理...
三、setup_device()跳到我们设备注册函数中去
}//初始化函数结束
(4)开始注册我们的这个设备
setup_device( ){ //安装(注册)一个设备前,一定要保证它被初始化了
这些成员都得出初始化好:
一、 int size; /* Device size in sectors */
u8 *data; /* The data array */
short users; /* How many users */
spinlock_t lock; /* For mutual exclusion */
struct request_queue *queue; /* The device request queue */
struct gendisk *gd; /* The gendisk structure */
二、add_disk(dev->gd);//这个重要的注册函数}//函数结束
(5)扇区大小、data数组、user、锁lock的初始化:
一、dev->size = nsectors*hardsect_size;
dev->data = vmalloc(dev->size);
spin_lock_init(&dev->lock);
二、//dev->queue = blk_alloc_queue(GFP_KERNEL); //RM_NOQUEUE
//dev->queue = blk_init_queue(sbull_full_request, &dev->lock); //RM_FULL
dev->queue = blk_init_queue(sbull_request, &dev->lock); //RM_SIMPLE
(6)告知内核硬件扇区尺寸、和timer模拟的初始化
blk_queue_logical_block_size(dev->queue, hardsect_size);
init_timer(&dev->timer);
dev->timer.data = (unsigned long) dev;
dev->timer.function = sbull_invalidate;gendisk初始化
一、初始化gendisk:
dev->gd = alloc_disk(SBULL_MINORS);
二、 初始化gendisk的成员
dev->gd->major = sbull_major;
dev->gd->first_minor = which*SBULL_MINORS;
dev->gd->fops = &sbull_ops;
dev->gd->queue = dev->queue;
dev->gd->private_data = dev;
(7)设置gendisk容量为xxx_size个扇区大小
set_capacity(dev->gd , nsectors*(hardsect_size / KERNEL_SECTOR_SIZE));
(8)剩下的就是为devices_operation结构体里声明的那些接口进行实现:
.open = sbull_open,
.release = sbull_release,
.media_changed = sbull_media_changed,
.revalidate_disk = sbull_revalidate,
.ioctl= sbull_ioctl,
.getgeo= sbull_getgeo,
一、sbull_open(struct block_device *bdev,fmode_t mode )
二、sbull_release(struct gendisk *bd_disk, fmode_t mode)
三、sbull_media_changed(struct gendisk *gd)
四、sbull_revalidate(struct gendisk *gd)
五、sbull_invalidate(unsigned long ldev)
六、sbull_ioctl (struct block_device *bdev, fmode_t mode,
unsigned int cmd, unsigned long arg)
七、sbull_getgeo(struct block_device *bdev, struct hd_geometry *geo)
以下是代码:
[cpp]viewplaincopyprint?
1./*
2. * Sample disk driver for 2.6.35.
3. */
4.
5.//#include
6.#include
7.#include
8.#include
9.
10.#include
11.#include
12.#include
13.#include
14.#include
15.#include
16.#include
17.#include
18.#include
19.#include
20.#include
21.#include
22.#include
23.#include
24.#include
25.
26.MODULE_LICENSE("Dual BSD/GPL");
27.
28.static int sbull_major = 0;
29.module_param(sbull_major, int, 0);
30.static int hardsect_size = 512;
31.module_param(hardsect_size, int, 0);
32.static int nsectors = 25600; /* How big the drive is */
33.module_param(nsectors, int, 0);
34.static int ndevices = 1;
35.module_param(ndevices, int, 0);
36.
37./*
38. * The different "request modes" we can use.
39. */
40.enum {
41. RM_SIMPLE = 0, /* The extra-simple request function */
42. RM_FULL = 1, /* The full-blown version */
43. RM_NOQUEUE = 2, /* Use make_request */
44.};
45.//static int request_mode = RM_FULL;
46.//static int request_mode = RM_SIMPLE;
47.static int request_mode = RM_NOQUEUE;
48.module_param(request_mode, int, 0);
49.
50./*
51. * Minor number and partition management.
52. */
53.#define SBULL_MINORS 16
54.#define MINOR_SHIFT 4
55.#define DEVNUM(kdevnum) (MINOR(kdev_t_to_nr(kdevnum)) >> MINOR_SHIFT
56.
57./*
58. * We can tweak our hardware sector size, but the kernel talks to us
59. * in terms of small sectors, always.
60. */
61.#define KERNEL_SECTOR_SIZE 512
62.
63./*
64. * After this much idle time, the driver will simulate a media change.
65. */
66.#define INVALIDATE_DELAY 60*HZ
67.
68./*
69. * The internal representation of our device.
70. */
71.struct sbull_dev {
72. int size; /* Device size in sectors */
73. u8 *data; /* The data array */
74. short users; /* How many users */
75. short media_change; /* Flag a media change?
*/
76. spinlock_t lock; /* For mutual exclusion */
77. struct request_queue *queue; /* The device request queue */
78. struct gendisk *gd; /* The gendisk structure */
79. struct timer_list timer; /* For simulated media changes */
80.};
81.
82.static struct sbull_dev *Devices = NULL;
83.
84./*
85. * Handle an I/O request.
86. */
87.static void sbull_transfer(struct sbull_dev *dev, unsigned long sector,
88. unsigned long nsect, char *buffer, int write)
89.{
90. unsigned long offset = sector*KERNEL_SECTOR_SIZE;
91. unsigned long nbytes = nsect*KERNEL_SECTOR_SIZE;
92. //printk("<0>""in %s offset=%d nbytes=%d write=%d\n",__FUNCTION__,offset,nbytes,write);
93. //buffer[10]='\0';
94. //printk(buffer);
95. //printk("\n");
96. if ((offset + nbytes) > dev->size) {
97. printk (KERN_NOTICE "Beyond-end write (%ld %ld)\n", offset, nbytes);
98. return;
99. }
100. if (write)
101. memcpy(dev->data + offset, buffer, nbytes);
102. else
103. memcpy(buffer, dev->data + offset, nbytes);
104.}
105.
106./*The simple form of the request function.*/
107.
108.static void sbull_request(struct request_queue *q)
109.{
110. struct request *req;
111.
112. req = blk_fetch_request(q);
113. while (req !
= NULL) {
114. struct sbull_dev *dev = req->rq_disk->private_data;
115. if (!
blk_fs_request(req)) {
116. printk (KERN_NOTICE "Skip non-fs request\n");
117. __blk_end_request_all(req, -EIO);
118. continue;
119. }
120. // printk (KERN_NOTICE "Req dev %d dir %ld sec %ld, nr %d f %lx\n",
121. // dev - Devices, rq_data_dir(req),
122. // req->sector, req->current_nr_sectors,
123. // req->flags);
124. // printk("sectors=%d\n",req->current_nr_sectors);
125. sbull_transfer(dev, blk_rq_pos(req), blk_rq_cur_sectors(req),
126. req->buffer, rq_data_dir(req));
127. if ( !
__blk_end_request_cur(req, 0) ) {
128. req = NULL;
129. }
130. }
131.}
132.
133.
134./*
135. * Transfer a single BIO.
136. */
137.static int sbull_xfer_bio(struct sbull_dev *dev, struct bio *bio)
138.{
139. int i;
140. struct bio_vec *bvec;
141. sector_t sector = bio->bi_sector;
142.
143. /* Do each segment independently. */
144. bio_for_each_segment(bvec, bio, i) {
145. char *buffer = __bio_kmap_atomic(bio, i, KM_USER0);
146. sbull_transfer(dev, sector, bio_cur_bytes(bio)>>9 ,
147. buffer, bio_data_dir(bio) == WRITE);
148. sector += bio_cur_bytes(bio)>>9;
149. __bio_kunmap_atomic(bio, KM_USER0);
150. }
151. return 0; /* Always "succeed" */
152.}
153.
154./*
155. * Transfer a full request.
156. */
157.static int sbull_xfer_request(struct sbull_dev *dev, struct request *req)
158.{
159. struct bio *bio;
160. int nsect = 0;
161.
162. __rq_for_each_bio(bio, req) {
163. sbull_xfer_bio(dev, bio);
164. nsect += bio->bi_size/KERNEL_SECTOR_SIZE;
165. }
166. return nse
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 实验 补充 sbull 虚拟 磁盘 驱动 编写