Linux块设备驱动之内存模拟块设备

用内存代替块设备的总结,相对来简单得多,对内存操作想必大家都很熟悉,直接分配一块内存就可以直接读写操作了
/* 参考:
 * drivers\block\xd.c
 * drivers\block\z2ram.c
 */
#define RAMBLOCK_SIZE (1024*1024)//一个扇区是512字节
 
static struct gendisk *ramblock_disk;
static struct request_queue *ramblock_queue;
static DEFINE_SPINLOCK(ramblock_lock);//定义一个自旋锁
static unsigned char *ramblock_buf;

static struct block_device_operations ramblock_fops = {//fops结构体,必须要。
.owner = THIS_MODULE,
.getgeo = ramblock_getgeo,//设置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 int ramblock_init(void)
{
/* 1. 分配一个gendisk结构体 */
ramblock_disk = alloc_disk(16); /* 次设备号个数: 分区个数+1 */
/* 2. 设置 */
/* 2.1 分配/设置队列: 提供读写能力 */
ramblock_queue = blk_init_queue(do_ramblock_request, &ramblock_lock);//do_ramblock_request请求队列函数
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打印到ramblock_disk->disk_name
ramblock_disk->fops        = &ramblock_fops;
set_capacity(ramblock_disk, RAMBLOCK_SIZE / 512);//设置容量
. 硬件相关操作 */
ramblock_buf = kzalloc(RAMBLOCK_SIZE, GFP_KERNEL);//分配一个读写缓冲区
/* 4. 注册 */
add_disk(ramblock_disk);
}

static void do_ramblock_request(struct request_queue * q)//当读写的时候调用这个函数
{
static int r_cnt = 0;
static int w_cnt = 0;
struct request *req;

//printk("do_ramblock_request %d\n", ++cnt);

while ((req = elv_next_request(q)) != NULL) {
/* 数据传输三要素: 源,目的,长度 */
/* 源/目的: */
unsigned long offset = req->sector * 512;//偏移值为

/* 目的/源: */
// req->buffer

/* 长度: */
unsigned long len = req->current_nr_sectors * 512;

if (rq_data_dir(req) == READ)
{
//printk("do_ramblock_request read %d\n", ++r_cnt);
memcpy(req->buffer, ramblock_buf+offset, len);
}
else
{
//printk("do_ramblock_request write %d\n", ++w_cnt);
memcpy(ramblock_buf+offset, req->buffer, len);
}
end_request(req, 1);//表示读写完成,必须写,不然会卡在那里,只有重新开关机
}
}
}

static void ramblock_exit(void)
{
unregister_blkdev(major, "ramblock");
del_gendisk(ramblock_disk);
put_disk(ramblock_disk);
blk_cleanup_queue(ramblock_queue);
kfree(ramblock_buf);
}

测试如下:
在开发板上:
1. insmod ramblock.ko
2. 格式化: mkdosfs /dev/ramblock
3. 挂接: mount /dev/ramblock /tmp/
4. 读写文件: cd /tmp, 在里面vi文件
5. cd /; umount /tmp/
6. cat /dev/ramblock > /mnt/ramblock.bin
7. 在PC上查看ramblock.bin
   sudo mount -o loop ramblock.bin /mnt

测试5th:
1. insmod ramblock.ko
2. ls /dev/ramblock*
3. fdisk /dev/ramblock
块设备常用的几个命令:
m:寻求帮助  n:增加一个新的分区  w:保存分区

你可能感兴趣的:(Linux块设备驱动之内存模拟块设备)