0%

ramdisk块设备

ramdisk 是基于内存,模拟创建出来的一个块设备。有时候我们开发的过程,需要了解下块设备成的一些原理,可以通过以下代码,去了解一个块设备的创建的过程。

源码

ramdisk.c文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/fs.h>
#include <linux/blkdev.h>
#include <linux/genhd.h>
#include <linux/hdreg.h>
#include <linux/vmalloc.h>
#include <linux/bio.h>

#define RAMDISK_SECTOR_SIZE 512
#define RAMDISK_SIZE (1024 * 1024 * 10) // 10MB

static int major_num = 0;
static struct request_queue *queue;
static struct gendisk *disk;
static unsigned char *ramdisk_data;

#if 0
static void
ramdisk_transfer(struct request *req)
{
struct bio_vec bvec;
struct req_iterator iter;
sector_t pos = blk_rq_pos(req);
unsigned int num_sectors = blk_rq_sectors(req);
unsigned int offset = pos * RAMDISK_SECTOR_SIZE;
///< unsigned int nbytes = num_sectors * RAMDISK_SECTOR_SIZE;

rq_for_each_segment(bvec, req, iter)
{
void *buffer = page_address(bvec.bv_page) + bvec.bv_offset;
if (rq_data_dir(req) == READ)
{
memcpy(buffer, ramdisk_data + offset, bvec.bv_len);
}
else
{
memcpy(ramdisk_data + offset, buffer, bvec.bv_len);
}
offset += bvec.bv_len;
}
}
#endif

static blk_qc_t
ramdisk_make_request(struct request_queue *q, struct bio *bio)
{
bio_endio(bio);
return BLK_QC_T_NONE;
}

static int
ramdisk_open(struct block_device *bdev, fmode_t mode)
{
printk("open ramdisk ...");
return 0;
}

static void
ramdisk_release(struct gendisk *gd, fmode_t mode)
{
printk("close ramdisk ...");
}

static struct block_device_operations fops =
{
.owner = THIS_MODULE,
.open = ramdisk_open,
.release = ramdisk_release,
};

static int __init ramdisk_init(void)
{
ramdisk_data = vmalloc(RAMDISK_SIZE);
if (!ramdisk_data)
{
return -ENOMEM;
}

major_num = register_blkdev(0, "ramdisk");
if (major_num <= 0)
{
vfree(ramdisk_data);
return -EBUSY;
}

queue = blk_alloc_queue(GFP_KERNEL);
if (!queue)
{
unregister_blkdev(major_num, "ramdisk");
vfree(ramdisk_data);
return -ENOMEM;
}

blk_queue_make_request(queue, ramdisk_make_request);
disk = alloc_disk(1);
if (!disk)
{
blk_cleanup_queue(queue);
unregister_blkdev(major_num, "ramdisk");
vfree(ramdisk_data);
return -ENOMEM;
}

strcpy(disk->disk_name, "ramdisk0");
disk->major = major_num;
disk->first_minor = 0;
disk->fops = &fops;
disk->queue = queue;
set_capacity(disk, RAMDISK_SIZE / RAMDISK_SECTOR_SIZE);
add_disk(disk);

return 0;
}

static void __exit ramdisk_exit(void)
{
del_gendisk(disk);
put_disk(disk);
blk_cleanup_queue(queue);
unregister_blkdev(major_num, "ramdisk");
vfree(ramdisk_data);
}

module_init(ramdisk_init);
module_exit(ramdisk_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("lpyuan");
MODULE_DESCRIPTION("RAM Disk Block Device Driver");

Makefile文件

1
2
3
4
5
6
obj-m += ramdisk.o

all:
make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules
clean:
make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean

reference

[1] https://blog.csdn.net/Alan445947767/article/details/39367445

[2] https://blog.csdn.net/weixin_37871174/article/details/75084619

小主,路过打个赏再走呗~