Chinaunix首页 | 论坛 | 博客
  • 博客访问: 934878
  • 博文数量: 63
  • 博客积分: 568
  • 博客等级: 中士
  • 技术积分: 3435
  • 用 户 组: 普通用户
  • 注册时间: 2012-10-05 11:44
文章分类
文章存档

2016年(4)

2015年(6)

2014年(3)

2013年(27)

2012年(23)

分类: LINUX

2013-11-17 11:50:53

前面已经说了Flash设备要和文件系统联系起来,首先在MTD Block层中抽象形成一个MTD Block设备,MTD Block层再想Block层注册Block设备,这样Flash就和磁盘系统一样呈现在内核中。本节来说一下MTD Block层是如何向Block层注册快设备的。

之前我们必须了解块设备世界中最关键的一个数据结构gendisk

struct gendisk 

    /* major, first_minor and minors are input parameters only, 
     * don't use directly.  Use disk_devt() and disk_max_parts(). 
     */ 
    int major;            /* major number of driver */ 
    int first_minor; 
    int minors;                     /* maximum number of minors, =1 for 
                                         * disks that can't be partitioned. */ 
 
    char disk_name[DISK_NAME_LEN];    /* name of major driver */ 
 
    /* Array of pointers to partitions indexed by partno. 
     * Protected with matching bdev lock but stat and other 
     * non-critical accesses use RCU.  Always access through 
     * helpers. 
     */ 
    struct disk_part_tbl *part_tbl; 
    struct hd_struct part0; 
 
    struct block_device_operations *fops; 
    struct request_queue *queue; 
    void *private_data; 
 
    int flags; 
    struct device *driverfs_dev;  // FIXME: remove 
    struct kobject *slave_dir; 
 
    struct timer_rand_state *random; 
 
    atomic_t sync_io;        /* RAID */ 
    struct work_struct async_notify; 
#ifdef  CONFIG_BLK_DEV_INTEGRITY 
    struct blk_integrity *integrity; 
#endif 
    int node_id; 
}; 

Gendisk从名字来看就是磁盘的一个抽象表示而已。其中主要数据结构有

Major 主设备号,对于mtdblock设备就是31

First_minor 第一个从设备号

Minors 主设备中有几个从设备

Disk_name 该块设备的名字

Disk_part_tbl 表示磁盘指向的分区数据结构

Hd_struct 表示一个分区数据结构

Request_queue 该磁盘上的请求队列

这里吧主要的数据结构做一个大概的说明,并不将所有的数据域做逐一分析。

 

MTD Block层在注册块设备时,首先必须申请一个gendisk数据结构并做相应的初始化

gd = alloc_disk(1 << tr->part_bits); 
if (!gd) 

    list_del(&new->list); 
    return -ENOMEM; 

gd->major = tr->major; 
gd->first_minor = (new->devnum) << tr->part_bits; 
gd->fops = &mtd_blktrans_ops; 
 
if (tr->part_bits) 
    if (new->devnum < 26
        snprintf(gd->disk_name, sizeof(gd->disk_name), 
                 "%s%c", tr->name, 'a' + new->devnum); 
    else 
        snprintf(gd->disk_name, sizeof(gd->disk_name), 
                 "%s%c%c", tr->name, 
                 'a' - 1 + new->devnum / 26
                 'a' + new->devnum % 26); 
else 
    snprintf(gd->disk_name, sizeof(gd->disk_name), 
             "%s%d", tr->name, new->devnum); 
 
/* 2.5 has capacity in units of 512 bytes while still 
   having BLOCK_SIZE_BITS set to 10. Just to keep us amused. */ 
set_capacity(gd, (new->size *tr->blksize) >> 9); 
 
gd->private_data = new
new->blkcore_priv = gd; 
gd->queue = tr->blkcore_priv->rq; 

上面初始化过程的代码比较简单,这里不再分析。向block层添加块设备主要发生在下面函数add_disk中。Add_disk完成的主要工作总结如下

1、block设备分配一个设备号

retval = blk_alloc_devt(&disk->part0, &devt); 

2、继续初始化gendisk中的数据成员

disk->major = MAJOR(devt); 
disk->first_minor = MINOR(devt); 

3、block设备管理系统中注册该设备

blk_register_region(disk_devt(disk), disk->minors, NULL, 
                    exact_match, exact_lock, disk); 

关于这个在block设备管理中注册的问题,这里稍微说一下,block设备管理中存在一个hash数组,管理了所有的block设备。这些设备按照设备号,被hash到这个bdev_map这个数组中去,并且将disk这个数据挂接到对应的hash项中。当内核要根据设备号查找disk数据的时候可以在这个hashbdev_map中轻而易举的找到。

4、接下来就是调用register_disk注册block设备,在我们分析的场景中,mtd block不允许再分区,register_disk实际上也就是初始了sys文件系统中的一些相关目录项

5、再调用blk_register_queue初始化sys下面IO调度队列相关的一些目录项

 

总结,通过上面的分析mtd blockblock层注册块设备,到目前为止实际上做了三件事情

1、分配了gendisk数据结构并将这个数据结构初始化

2、将块设备按其设备号注册到bdev_map hash表中,hash表项中有指针指向了gendisk

3、初始化和该块设备相关的sys中的表项

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