您的位置:首页 > 其它

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

2015-02-04 11:43 330 查看
/*既然上面分析了,块设备的工作原理。 那如何写一个块设备呢?*/

/*怎么写一个块设备驱动程序?
* 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");
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  块设备