这里直接引用大佬的文章,讲解蛮清楚的。
块设备驱动程序设计(1)—块设备系统架构
//参考 drivers/block/mg_disk.c
//drivers/block/z2ram.c
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define RAMBLOCK_SIZE (1024*1024)
static DEFINE_SPINLOCK(ramblock_lock);
static struct gendisk *ramblock_disk;
static struct request_queue *ramblock_queue;
static int major;
static unsigned char *ramblock_buf;
//为了可以使用分区工具fdisk,内存可以假设成类似磁盘也有头 heads,柱面 cylinders,扇区 sectors
static int ramblock_getgeo(struct block_device *bdev, struct hd_geometry *geo)
{
/* 容量=heads*cylinders*sectors*512 */
geo->heads = 2;
geo->cylinders = 32;
geo->sectors = RAMBLOCK_SIZE/2/32/512;
return 0;
}
static const struct block_device_operations ramblock_fops =
{
.owner = THIS_MODULE,
.getgeo = ramblock_getgeo,//几何信息
};
static void ramblock_request(struct request_queue *q)
{
struct request *req;
static int r_cnt = 0, w_cnt = 0;
//从队列中取出要处理的一个请求
req = blk_fetch_request(q);
while (req != NULL)
{
//源/目的
unsigned long offset = blk_rq_pos(req) << 9;// * 512
//目的/源
void *buffer = bio_data(req->bio);
//长度
unsigned long len = blk_rq_cur_bytes(req);
if (rq_data_dir(req) == READ)
{
printk("%s read %d\n", __FUNCTION__, ++r_cnt);
memcpy(buffer, offset + ramblock_buf, len);
}
else
{
printk("%s write %d\n", __FUNCTION__, ++w_cnt);
memcpy(offset + ramblock_buf, buffer, len);
}
if (!__blk_end_request_cur(req, 0))
{
req = blk_fetch_request(q);
}
}
}
static int ramblock_init(void)
{
/* 1. 分配一个gendisk结构体 */
ramblock_disk = alloc_disk(16);/* 次设备号个数: 分区个数+1 */
/* 2. 设置 */
/* 2.1 分配/设置队列: 提供读写能力 */
ramblock_queue = blk_init_queue(ramblock_request, &ramblock_lock);
ramblock_disk->queue = ramblock_queue;
/* 2.2 设置其他属性: 比如容量 */
major = register_blkdev(0, "ramblock");/* cat /proc/devices */
ramblock_disk->major = major;
ramblock_disk->first_minor = 0;
sprintf(ramblock_disk->disk_name, "ramblock");
ramblock_disk->fops = &ramblock_fops;
set_capacity(ramblock_disk, RAMBLOCK_SIZE / 512);
/* 3. 硬件相关操作 */
ramblock_buf = kzalloc(RAMBLOCK_SIZE, GFP_KERNEL);
/* 4. 注册 */
add_disk(ramblock_disk);
return 0;
}
static void ramblock_exit(void)
{
// blk_unregister_region(MKDEV(Z2RAM_MAJOR, 0), Z2MINOR_COUNT);
unregister_blkdev(major, "ramblock");
del_gendisk(ramblock_disk);
put_disk(ramblock_disk);
blk_cleanup_queue(ramblock_queue);
kfree(ramblock_queue);
}
module_init(ramblock_init);
module_exit(ramblock_exit);
MODULE_LICENSE("GPL");
/ # insmod ramblock.ko
ramblock_request read 1
ramblock: unknown partition table
/ # ls -l /dev/ramblock
brw------- 1 0 0 254, 0 Jan 1 00:24 /dev/ramblock
/ # fdisk dev/ramblock //分区工具
ramblock_request read 2
ramblock_request read 3
ramblock_request read 4
ramblock_request read 5
Device contains neither a valid DOS partition table, nor Sun, SGI, OSF or GPT disklabel
Building a new DOS disklabel. Changes will remain in memory only,
until you decide to write them. After that the previous content
won't be recoverable.
Command (m for help): m //查看帮助
Command Action
a toggle a bootable flag
b edit bsd disklabel
c toggle the dos compatibility flag
d delete a partition
l list known partition types
n add a new partition
o create a new empty DOS partition table
p print the partition table
q quit without saving changes
s create a new empty Sun disklabel
t change a partition's system id
u change display/entry units
v verify the partition table
w write table to disk and exit
x extra functionality (experts only)
Command (m for help): n //增加分区
Command action
e extended
p primary partition (1-4)
p //主分区
Partition number (1-4): 1
First cylinder (1-32, default 1): 1
Last cylinder or +size or +sizeM or +sizeK (1-32, default 32): 5
Command (m for help): p
Disk dev/ramblock: 1 MB, 1048576 bytes
2 heads, 32 sectors/track, 32 cylinders
Units = cylinders of 64 * 512 = 32768 bytes
Device Boot Start End Blocks Id System
dev/ramblock1 1 5 144 83 Linux
Command (m for help): n
Command action
e extended
p primary partition (1-4)
p
Partition number (1-4): 2
First cylinder (6-32, default 6): 6
Last cylinder or +size or +sizeM or +sizeK (6-32, default 32): 32
Command (m for help): p
Disk dev/ramblock: 1 MB, 1048576 bytes
2 heads, 32 sectors/track, 32 cylinders
Units = cylinders of 64 * 512 = 32768 bytes
Device Boot Start End Blocks Id System
dev/ramblock1 1 5 144 83 Linux
dev/ramblock2 6 32 864 83 Linux
Command (m for help): w
The partition table has been altered.ramblock_request write 1
Calling ioctl() to re-read partition table
ramblock_request read 6
ramblock: ramblock1 ramblock2
/ # ls dev/ramblock*
dev/ramblock dev/ramblock1 dev/ramblock2
/ # ls dev/ramblock* -l
brw------- 1 0 0 254, 0 Jan 1 00:28 dev/ramblock
brw------- 1 0 0 254, 1 Jan 1 00:28 dev/ramblock1
brw------- 1 0 0 254, 2 Jan 1 00:28 dev/ramblock2
/ # mkdosfs dev/ramblock1
ramblock_request read 7
ramblock_request read 8
ramblock_request write 2
ramblock_request write 3
/ # mount /dev/ramblock1 /mnt
ramblock_request read 9
ramblock_request read 10
ramblock_request read 11
ramblock_request read 12
ramblock_request read 13
ramblock_request read 14
ramblock_request read 15
ramblock_request read 16
ramblock_request read 17
ramblock_request read 18
ramblock_request read 19
ramblock_request write 4
/ # ls /mnt
/ # umount /mnt/
ramblock_request write 5