原创 块设备驱动编写总结二

2008-7-3 08:44 5146 6 8 分类: 软件与OS

初始化一个块设备



 



每个块设备都拥有一个操作接口:struct block_device_operations,该接口定义了opencloseioctl等函数接口,但没有,也没有必要定义readwrite函数接口。



 



初始化一个块设备的过程如下:



int setup_device(block_dev_t
*dev, int minor)



{



       int hardsect_size = HARDSECT_SIZE;



       int chunk_size;



       sector_t dev_size;



      



       /* 分配一个请求队列 */



       dev->queue =
blk_alloc_queue(GFP_KERNEL);



       if (dev->queue == NULL) {



              printk(ERROR,
"blk_alloc_queue failure!\n");



              return -ENOMEM;



       }



 



       chunk_size = dev->chunk_size >>
9;    //sectors



 



       /* block_make_request注册到q->make_request */



       blk_queue_make_request(dev->queue, block_make_request);



      



       blk_queue_max_sectors(dev->queue,
chunk_size);



       blk_queue_hardsect_size(dev->queue,
hardsect_size);



       blk_queue_merge_bvec(dev->queue, block_mergeable_bvec);



 



       dev->queue->queuedata = dev;



       /* block_unplug注册到q->unplug_fn */



       dev->queue->unplug_fn = block_unplug;



      



       /* 分配一个gendisk */



       dev->gd = alloc_disk(1);



       if (!dev->gd) {



              prink(ERROR, "alloc_disk
failure!\n");



              blk_cleanup_queue(dev->queue);



              return -ENOMEM;



       }



      



       dev->gd->major = block_major;               /* 设备的major */



       dev->gd->first_minor = minor;            /* 设备的minor */



       dev->gd->fops = &block_ops;                 /* 块设备的操作接口,opencloseioctl */



       dev->gd->queue = dev->queue;           /* 块设备的请求队列 */



       dev->gd->private_data = dev;                    



       snprintf(dev->gd->disk_name, 32,
dev->block_name);



 



       dev_size = (sector_t) dev->dev_size
>> 9;  



       set_capacity(dev->gd, dev_size);         /* 设置块设备的容量 */



 



       add_disk(dev->gd);                                   /* 添加块设备 */



 



       return 0;



}



 



注册/释放一个块设备



       通过register_blkdev函数将块设备注册到Linux系统。示例代码如下:



 



static int blockdev_init(void)



{



      



 



block_major =
register_blkdev(block_major, "blockd");



       if
(block_major <= 0) {



              printk(ERROR,
"blockd: cannot get major %d\n", block_major);



              return
-EFAULT;



       }



      





}



 



       通过unregister_blkdev函数清除一个块设备。示例代码如下:



static int blockdev_cleanup(void)



{



      



 



unregister_blkdev(block_major,
"blockd");



 





}



make_request函数



make_request函数是块设备中最重要的接口函数,每个块设备都需要提供make_request函数。如果块设备为有请求队列的实际设备,那么make_request函数被注册为__make_request,该函数由Linux系统提供;反之,需要用户提供私有函数。__make_request函数功能在前文已述。



 



在用户提供的私有make_request函数中往往对bio进行过滤处理,这样的驱动在Linux中有mdraid0raid1raid5),过滤处理完毕之后,私有make_request函数返回1,告诉generic_make_request函数进行bio转发。





文章评论2条评论)

登录后参与讨论

wangxinfeng6666_749290079 2013-7-2 17:56

写的好

用户411565 2008-7-7 09:16

块设备驱动编写总结二是《块设备编写总结》的第二部分,第一部分讲述了块设备编写的原理、数据流程。欢迎大家讨论。
相关推荐阅读
用户411565 2012-12-18 12:58
我的存储之道博客
大家好,最近一直在做存储方面的工作,所以我在51CTO上专门开辟了一个空间讨论存储相关的问题,喜欢存储的朋友可以可以访问我的存储博客: 存储之道 (http://alanwu.blog.51cto...
用户411565 2012-04-06 21:39
SAS Cable可以有多长?
SAS接口是高端硬盘的主流接口,是存储系统的理想选择。我们知道高速信号的传输距离和传输线相关的,那么SAS作为外部通信接口,其Cable线具体可以有多长呢? 我在网上找到上图所示的眼图测...
用户411565 2012-04-06 21:38
对TRIM SCSI命令的一些分析
前一段时间做了一些对SSD方面进行优化的工作,SSD最大的问题在于长时间使用之后,IO性能会急剧下降。其主要问题在于为了防止“写放大”问题的产生,SSD的firmware采用了类似于log方式的算...
用户411565 2012-04-06 21:35
惊叹!我们的跨洋网络
  每次地质自然灾害的时候,总会伴随着网络的问题,这是由于我们的越洋光纤网络出了故障,受到自然力的破坏而导致断裂。越洋光纤,听起来的确是件非常不可思议的事情,工程量非常的巨大,但正是如此伟大的...
用户411565 2012-04-06 21:33
科学仪器网络模型
科学仪器概述     科学仪器发展趋势 科学是从测量开始的,科学仪器是信息技术的源头,是信息产业的重要组成部分,是现代科学与工业的基石。科学仪器产业的发展关系到国家科学研究实力、生...
用户411565 2012-04-06 21:16
谈谈RAID产品与技术
说起RAID,学计算机的同学马上会说RAID技术简单啊,就是将数据条带化,然后计算一些冗余数据,一并写入磁盘。通过RAID技术一方面提高系统的IO性能;另一方面提高系统的可靠性。单纯从RAID的原...
我要评论
2
6
关闭 站长推荐上一条 /2 下一条