前面已经说了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数据的时候可以在这个hash表bdev_map中轻而易举的找到。
4、接下来就是调用register_disk注册block设备,在我们分析的场景中,mtd block不允许再分区,register_disk实际上也就是初始了sys文件系统中的一些相关目录项
5、再调用blk_register_queue初始化sys下面IO调度队列相关的一些目录项
总结,通过上面的分析mtd block想block层注册块设备,到目前为止实际上做了三件事情
1、分配了gendisk数据结构并将这个数据结构初始化
2、将块设备按其设备号注册到bdev_map hash表中,hash表项中有指针指向了gendisk
3、初始化和该块设备相关的sys中的表项
阅读(20933) | 评论(0) | 转发(2) |