Chinaunix首页 | 论坛 | 博客
  • 博客访问: 166075
  • 博文数量: 22
  • 博客积分: 1632
  • 博客等级: 上尉
  • 技术积分: 490
  • 用 户 组: 普通用户
  • 注册时间: 2008-09-01 14:28
文章分类

全部博文(22)

文章存档

2010年(10)

2009年(3)

2008年(9)

分类: LINUX

2010-04-07 15:38:26

初始化一个块设备

 

每个块设备都拥有一个操作接口: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

阅读(2954) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~