块设备驱动

 

for (i = 0; i < nr; i++) {

struct buffer_head *bh = bhs[i];

submit_bh(rw, bh);

struct bio *bio; // 使用bh来构造bio (block input/output)

submit_bio(rw, bio);

// 通用的构造请求: 使用bio来构造请求(request)

generic_make_request(bio);

__generic_make_request(bio);

request_queue_t *q = bdev_get_queue(bio->bi_bdev); // 找到队列

 

// 调用队列的"构造请求函数"

ret = q->make_request_fn(q, bio);

// 默认的函数是__make_request

__make_request

// 先尝试合并

elv_merge(q, &req, bio);

 

// 如果合并不成,使用bio构造请求

init_request_from_bio(req, bio);

 

// 把请求放入队列

add_request(q, req);

 

// 执行队列

__generic_unplug_device(q);

// 调用队列的"处理函数"

q->request_fn(q);

   

驱动程序

1 /*
2 * 块设备驱动程序:内存用作磁盘
3 * 参考:
4 * .linux-2.6.22.6driverslockxd.c
5 * .linux-2.6.22.6driverslockz2ram.c
6 */
7
8 #include <linux/module.h>
9 #include <linux/errno.h>
10 #include <linux/interrupt.h>
11 #include <linux/mm.h>
12 #include <linux/fs.h>
13 #include <linux/kernel.h>
14 #include <linux/timer.h>
15 #include <linux/genhd.h>
16 #include <linux/hdreg.h>
17 #include <linux/ioport.h>
18 #include <linux/init.h>
19 #include <linux/wait.h>
20 #include <linux/blkdev.h>
21 #include <linux/blkpg.h>
22 #include <linux/delay.h>
23 #include <linux/io.h>
24
25 #include <asm/system.h>
26 #include <asm/uaccess.h>
27 #include <asm/dma.h>
28
29 /* 1M */
30 #define RAMBlock_SIZE (1024*1024)
31
32 static unsigned char *ramBlock_buf;
33
34 static struct gendisk *ramBlock_disk;
35 static request_queue_t *ramBlock_queue;
36
37 static int major;
38
39 /* 自旋锁 */
40 static DEFINE_SPINLOCK(ramBlock_lock);
41
42 //为了使用fdisk分区工具,假装自己是磁盘,
43 //有2个面,32个环,RAMBlock_SIZE/heads/cylinders/512个扇区
44 //容量:RAMBlock_SIZE = heads*cylinders*sectors*512
45 //1 disk                 = 2 heads
46 //1 heads                  = 32 cylinders
47 //1 cylinders        = RAMBlock_SIZE/heads/cylinders/512 sectors = 32 sectors
48 static int ramBlock_getgeo(struct block_device *bdev, struct hd_geometry *geo)
49 {
50         geo->heads                 = 2;
51         geo->cylinders         = 32;
52         geo->sectors         = 32;
53         return 0;
54 }
55
56
57 static struct block_device_operations ramBlock_fops = {
58         .owner = THIS_MODULE,
59         .getgeo = ramBlock_getgeo,
60 };
61
62 static void do_ramBlock_request(request_queue_t *q)
63 {
64         static int r_cnt = 0;
65         static int w_cnt = 0;
66         struct request *req;
67
68         //以电梯调度算法,取出下一个请求
69         while ((req = elv_next_request(q)) != NULL) {
70                 /* 6 读写 */
71                 //数据传输三要素:源、目的、长度
72                 //源/目的        (要操作第几个扇区)
73                 unsigned long offset = req->sector << 9;        //<< 9 相当于 * 512
74
75                 //目的/源        (读、写缓冲区)
76                 //req->buffer
77
78                 //长度        (缓冲区长度(sector的倍数))
79                 unsigned long len = req->current_nr_sectors << 9;
80
81                 //读数据
82                 if (rq_data_dir(req) == READ)
83                 {
84                         printk("do_ramblock_request read %d ", ++r_cnt);
85                         memcpy(req->buffer, ramBlock_buf+offset, len);
86                 }
87                 else {        //写数据
88                         printk("do_ramblock_request read %d ", ++r_cnt);
89                         memcpy(ramBlock_buf+offset, req->buffer, len);
90                 }
91
92                 /******** 6 end ********/
93                 end_request(req, 1);
94         }
95         return;
96 }
97
98
99 /* 1 出入口函数 */
100 static int ramBlock_init(void)
101 {
102         /* 2 分配一个gendisk结构体 */
103         ramBlock_disk = alloc_disk(16); //次设备号个数:分区个数+1
104         /******** 2 end ********/
105
106         /* 3 设置 */
107         //3.1 分配/设置队列(提供读写功能)
108         ramBlock_queue = blk_init_queue(do_ramBlock_request, &ramBlock_lock);        
109         
110         //3.2 设置其他属性:如容量
111         ramBlock_disk->queue                = ramBlock_queue;
112
113         major = register_blkdev(0, "ramBlock_disk");                //cat /proc/devices
114         ramBlock_disk->major                = major;
115
116         ramBlock_disk->first_minor        = 0;
117         sprintf(ramBlock_disk->disk_name, "ramBlock_disk");
118         ramBlock_disk->fops                        = &ramBlock_fops;
119         set_capacity(ramBlock_disk, RAMBlock_SIZE/512);                //第二个参数表示扇区个数,相对于内核而言,一个扇区为512字节
120         /******** 3 end ********/
121
122         /*
123          * 除了第4、第6、及以后的操作外,实际已经完成了块设备驱动框架的编写;        
124          */
125
126         /* 4 硬件相关的操作 */
127         ramBlock_buf = kzalloc(RAMBlock_SIZE, GFP_KERNEL);
128         /******** 4 end ********/
129
130         /* 5 注册 */
131         add_disk(ramBlock_disk);
132         /******** 5 end ********/
133         return 0;
134 }
135
136
137 static void ramBlock_exit(void)
138 {
139         unregister_blkdev(major, "ramBlock_disk");
140         del_gendisk(ramBlock_disk);
141         put_disk(ramBlock_disk);
142         blk_cleanup_queue(ramBlock_queue);
143         kfree(ramBlock_buf);
144         return;
145 }
146
147 module_init(ramBlock_init);
148 module_exit(ramBlock_exit);
149 MODULE_LICENSE("GPL");
150 /******** 1 end ********/

   

   

调试

1. insmod ramBlock.ko

   

2. 格式化:

mkdosfs /dev/ramBlock_disk

   

3. 挂接:

mount /dev/ramBlock_disk /tmp

   

4. 读写文件:

cd /tmp

vi 1.txt

   

(分区:fdisk /dev/ramBlock_disk)

   

5. 卸载

cd /

umount /tmp/

   

6. 把/dev/ramBlock_disk目录下的文件,以镜像的形式保存到/mnt下

cat /dev/ramBlock_disk > /mnt/ramBlock_disk.bin

   

7. 在PC上查看ramBlock_disk.bin(把ramBlock_disk.bin作为回环设备挂接到/mnt)

sudo mount -o loop ramBlock_disk.bin /mn

  

原文地址:https://www.cnblogs.com/lilto/p/11878255.html