Linux块设备总结(六)块设备子系统初始化

在上两篇博客中我们学习了块设备子系统数据组织结构,但是块设备子系统的总体上的初始化还没有涉及到,本章就开始学习块设备子系统的一系列初始化。
块设备子系统简而言之是Linux中管理块设备的一个子系统,是Linux中一个重要的子系统,没有块设备子系统我们的硬盘,光驱,USB在我们的linux 系统中都不可能感知,更别提热插拔的USB了。
块设备主要的子系统的初始话是在genhd_device_init函数中下面就依照这个函数来进行解析:

static int __init genhd_device_init(void)
{
     
        int error;

        block_class.dev_kobj = sysfs_dev_block_kobj;
        error = class_register(&block_class);    //块设备类的注册
        if (unlikely(error))					//如果错误返回错误值
                return error;
        bdev_map = kobj_map_init(base_probe, &block_class_lock);  //块设备的管理初始化,主要管理着255个散列表,用于申请块设备以及注册块设备的时候时候
        blk_dev_init();				//块设备最基础的设备使用

        register_blkdev(BLOCK_EXT_MAJOR, "blkext");			//注册设备号为259的块设备文件系统

#ifndef CONFIG_SYSFS_DEPRECATED
        /* create top-level block dir */
        block_depr = kobject_create_and_add("block", NULL);  //用于在驱动模型中/sys目录下生成block目录
#endif
        return 0;
}

以上函数看起来很容易,但是俗话说:麻雀虽小五脏俱全。如果仔细理解的话可能就不太容易理解了,下面先对于函数中各个变量做一个简短的说明。

struct class block_class;
主要使用类设备的链表结构,把gendisk结构放入block_class类的private->class_device->i_klist链表下面便于寻找
struct kobj_map  * bdev_map;
主要使用此散列表完成每个主设备号下面维护着若干个链表,每个链表每个节点下注册若干个块次设备号
struct kobject block_depr;
主要完成在/sys目录下生成一个block目录

各个不同的简略说明已经在注释中有说明,下面对各个不同的调用进行一一说明。

class_register(&block_class);

说明此函数之前我们先看一下此函数前后的调用关系,主要有两句C语言调用,如下:

        block_class.dev_kobj = sysfs_dev_block_kobj;
        error = class_register(&block_class); 

其中block_class变量是一个全局变量,定义在genhd_device_init函数上面。sysfs_dev_block_kobj也是一个全局变量,其主要作用是在/sys/dev/驱动模型下面生成一个block目录,并在class_register调用之后完成block_class注册。
我们再看一下block_class的作用,如下图:
在这里插入图片描述
其主要作用是在block_class->p->class_device->i_klist下面链接各个通用磁盘,链接的通用磁盘指针在上图有说明,不一一细说。然后在遍历驱动的时候先根据主磁盘的设备号查找磁盘,找到主设备号之后,然后根据次设备号查找磁盘分区。比较方便。

kobj_map_init(base_probe, &block_class_lock)

主要生成bdev_map全局变量,bdev_map为块设备驱动的散列表,主要管理着块设备驱动注册时候主设备号和次设备号的申请和释放。
bdev_map散列表总共有255个链表节点,每个链表节点下面有若干个节点组成,块设备在注册的时候用于查找未使用的主次设备号。

bdev_init

此函数原型如下:

int __init blk_dev_init(void)
{
                    
        BUILD_BUG_ON(__REQ_NR_BITS > 8 *
                        sizeof(((struct request *)0)->cmd_flags));

        kblockd_workqueue = create_workqueue("kblockd");
        if (!kblockd_workqueue)
                panic("Failed to create kblockd\n");
        
        request_cachep = kmem_cache_create("blkdev_requests",
                        sizeof(struct request), 0, SLAB_PANIC, NULL);
        
        blk_requestq_cachep = kmem_cache_create("blkdev_queue",
                        sizeof(struct request_queue), 0, SLAB_PANIC, NULL);

        return 0;
}

其函数主要有如下功能:

1.创建一个名为kblocked的工作队列。
2.建立一个缓存池,主要是为了request_list申请和释放使用的。
3.建立名为blkdev_queue的缓存池,主要是为了request_queue建立一个缓存池。用于request_queue的申请和释放。

register_blkdev(BLOCK_EXT_MAJOR, “blkext”);

主要建立bdev文件系统。bdev文件系统的作用已经在之前有所涉及,不在赘述。

你可能感兴趣的:(内核,块设备,Linux内核架构,块设备,内核,块设备初始化)