== Structure == 块设备的驱动包括几部分,如下: 0 首先,内核要支持,块子系统。 genhd_device_init() 1 想想设备,你最先可能想到什么呢?没错,设备号! major_names管理整个系统的块设备号和设备名字的单一关系,除了名字之外找不到和实际设备的任何关系,固步自封的感觉。 register_blkdev()用来向major_names一个设备号,反之unregister_blkdev。 2 说到内核,结构设计堪称一绝,怎么个绝法?结构乃内核之根本。 我们知道unix,秉持着一切皆文件的思想,所以块设备的结构涉及到fs 和 硬件抽象两方面。 涉及到块设备结构,主要三个。 gendisk对一个硬件设备只有一个,由我们编写驱动时创建,被blk_register_region() hash在bdev_map。 block_device: 由内核创建,对应整个硬盘和分区,数量为分区数+1. hdstruct:由内核创建,词汇对应分区具体数据和block_deviceblock一样。 3 bdev_map 在blk_register_region()中hash了所有的gendisk 4 devtmpfs 这个文件系统是完成/dev下面设备的节点的创建。 5 bdev pseudo filesytem 配合inode hashtable 找到 block_device。 在设备刚注册时和打开一个新分区时用到。目的是建立/dev下inode 和block_device的联系。 == Understand == 内核加载驱动驱动时,驱动的执行过程 =================== 0 首先,申请设备号 1 关闭或者启用request queue。 关闭request queue:blk_queue_make_request传进去一个自己写的不用处理queue的函数,就是终极函数了。 如果还想使用queue,blk_alloc_queue,自己申请一个。 开启request queue: 这个用blk_init_queue 传进去一个request_fn就好了,这个也是终极函数。 2 alloc_disk创建gendisk 3 add_disk 向系统添加gendisk。这个过程最复杂包括: 3.1 hash gendisk 到bdev_map 3.2 register_disk: 前半部分加到kernel moudle model, device_add,创建一个req结构,会被devtempfsd动态处理掉,在/dev下创建一个entry的inode。 此处,对比下char设备,可以用device_create()和mknod shell 命令两种方式。 device_create 也是通过device_add 到devtmpfsd创建/dev节点的indoe。 mknod这个shell命令和devtmpfsd 是两回事,mknode的切入路径是sys_mknod.不过最终都调用vfs_mknod. udev知识在节点上做些装饰,真的设备节点还是由mknod和devtmpfsd创建的,以前一直混着。 块设备的节点,我们无法自己手动创建,而字符的可以。 中部分:bdget_disk() 在bdev psueudo 创建bdev_inode register_disk产生了两个inode,第一个在文件系统/dev下面的。 创建第一个inode后,init_special_inode 就会被调用,赋值def_blk_fops给inode的i_fop见ext3_read_inode 负责fs相关的内容。 另一个inode是bdev pseudo filesystem里面的,这个是为了快速找到block_device,这个inode通常秘不示人,不必关心。 负责和blk设备抽象的内容。这个inode是在后面blkdev_open->bd_acquire用到。 具体的用法是,bd_acquire->bdget->iget5_locked,更具体: find_inode 将用设备号和blockdev_superblock的hash值在inode_hashtable中找到对应sb 和devt的inode。 有了这个inode就找到了block_device. bd_acquire的最重要works是建立devtmpfs的inode->i_bdev和block_device的联系。 后半部分是blkdev_get,建立block_device gendisk hdstruct三者联系。 3.4blk_register_queue() 名不见经传。 |
|
来自: clover_xian > 《我的图书馆》