前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >内存模拟块设备驱动程序设计

内存模拟块设备驱动程序设计

作者头像
DragonKingZhu
发布2022-05-08 16:13:21
1.3K0
发布2022-05-08 16:13:21
举报
代码语言:javascript
复制
/*既然上面分析了,块设备的工作原理。 那如何写一个块设备呢?*/

/*怎么写一个块设备驱动程序?
* 1. 分配一个gendisk结构,用alloc_disk函数
* 2. 分配一个request队列,用blk_init_queue函数
* 3. 设置gendisk结构
* 3.1 设置主设备号,次设备号
* 3.2 设置block_device_operations结构
* 3.3 设置queueu结构
* 4. 注册gendisk:     用add_disk函数     
*/

/***既然知道如何写一个块设备驱动程序,我们就动手用内存模拟一个块设备驱动***/

#define BLOCK_SIZE (1024*1024)
static struct gendisk *block_disk;
struct request_queue *block_queue;
static DEFINE_SPINLOCK(block_lock);
static int major;
static unsigned char *block_buf;

//硬盘容量 = 柱面数(表示每面盘面上有几条磁道,一般总数是1024) × 磁头数(表示盘面数) × 扇区数(表示每条磁道有几个扇区,一般总数是64)× 扇区(存储基本单元,大小一般为512B/4KB)
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 z2_fops =
{
	.owner	= THIS_MODULE,
	.getgeo	= block_getgeo,
};

static void block_request_func(request_queue_t * q)
{
		struct request *req;
	  while ((req = elv_next_request(q)) != NULL) {
		/* 数据传输三要素: 源,目的,长度 */
		
		unsigned long offset = req->sector * 512;

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

		if (rq_data_dir(req) == READ)//读设备
		{
			memcpy(req->buffer, ramblock_buf+offset, len);
		}
		else  //写设备
		{
			memcpy(ramblock_buf+offset, req->buffer, len);
		}		
		
		end_request(req, 1);
}

static int block_init(void)
{
	//1. 	分配一个gendisk结构,用alloc_disk函数
	block_disk = alloc_disk(10); //10个分区
		
	//2.  分配一个request队列,用blk_init_queue函数
	block_queue = blk_init_queue(block_request_func, &block_lock);
	
	//设置queueu结构
	block_disk->queue = block_disk;
	
	//3.  设置gendisk结构
	major = register_blkdev(0, "block");
	block_disk->major = major;
	block_disk->first_minor = 0;
	block_disk->fops = &block_fops;
	sprintf(block_disk->disk_name, "myblock");
	set_capacity(ramblock_disk, BLOCK_SIZE / 512); //设置容量
	
	//既然我们用内存模拟块设备,需要分配一块内存
	block_disk = kzalloc(BLOCK_SIZE, GFP_KERNEL);
	
	//4.  注册gendisk:     用add_disk函数
	add_disk(block_disk);
}

//释放申请的内存
static void block_exit(void)
{
	unregister_blkdev(major, "myblock");
	del_gendisk(block_disk);
	put_disk(block_disk);
	blk_cleanup_queue(block_disk);
	kfree(block_disk);
}

module_init(block_init);
module_exit(block_exit);

MODULE_LICENSE("GPL");
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2015-02-04,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档