您的位置:首页 > 运维架构 > Linux

Linux那些事儿之我是Block层(3)驱动不过一出戏,alloc_disk内存申请为哪般?

2014-08-29 15:42 381 查看
下一个函数,alloc_disk().在sd.c中咱们传递进来的参数是16.

    720 struct gendisk *alloc_disk(int minors)

    721 {

    722         return alloc_disk_node(minors, -1);

    723 }

    724

    725 struct gendisk *alloc_disk_node(int minors, int node_id)

    726 {

    727         struct gendisk *disk;

    728

    729         disk = kmalloc_node(sizeof(struct gendisk), GFP_KERNEL, node_id);

    730         if (disk) {

    731                 memset(disk, 0, sizeof(struct gendisk));

    732                 if (!init_disk_stats(disk)) {

    733                         kfree(disk);

    734                         return NULL;

    735                 }

    736                 if (minors > 1) {

    737                         int size = (minors - 1) * sizeof(struct hd_struct *);

    738                         disk->part = kmalloc_node(size, GFP_KERNEL, node_id);

    739                         if (!disk->part) {

    740                                 kfree(disk);

    741                                 return NULL;

    742                         }

    743                         memset(disk->part, 0, size);

    744                 }

    745                 disk->minors = minors;

    746                 kobj_set_kset_s(disk,block_subsys);

    747                 kobject_init(&disk->kobj);

    748                 rand_initialize_disk(disk);

    749                 INIT_WORK(&disk->async_notify,

    750                         media_change_notify_thread);

    751         }

    752         return disk;

    753 }

因此我们做的事情就是申请了一个struct gendisk结构体.毫无疑问,这个结构体是我们这个故事中最重要的结构体之一,来自include/linux/genhd.h:

    113 struct gendisk {

    114         int major;                      /* major number of driver */
    115         int first_minor;
    116         int minors;                     /* maximum number of minors, =1 for
    117                                          * disks that can't be partitioned. */
    118         char disk_name[32];             /* name of major driver */
    119         struct hd_struct **part;        /* [indexed by minor] */
    120         int part_uevent_suppress;
    121         struct block_device_operations *fops;
    122         struct request_queue *queue;
    123         void *private_data;
    124         sector_t capacity;
    125
    126         int flags;
    127         struct device *driverfs_dev;
    128         struct kobject kobj;
    129         struct kobject *holder_dir;
    130         struct kobject *slave_dir;
    131
    132         struct timer_rand_state *random;
    133         int policy;
    134
    135         atomic_t sync_io;               /* RAID */
    136         unsigned long stamp;
    137         int in_flight;
    138 #ifdef  CONFIG_SMP
    139         struct disk_stats *dkstats;
    140 #else
    141         struct disk_stats dkstats;
    142 #endif
    143         struct work_struct async_notify;
    144 };

因为minors我们给的是16,所以736行的if语句肯定是满足的.于是size等于15个sizeof(struct
hd_struct *),而part我们看到是struct hd_struct的二级指针,这里我们看到kmalloc_node(),这个函数中的node/node_id这些概念指的是NUMA技术中的节点,对于咱们这些根本就不会接触NUMA的人来说kmalloc_node()就等于kmalloc(),因此这里做的就是申请内存并且初始化为0.要说明的一点是,part就是partition的意思,日后它将扮演我们常说的分区的角色.
然后,disk->minors设置为了16.
746行,kobj_set_kset_s(),block_subsys是我们前面注册的子系统,从数据结构来说,它的定义如下,来自block/genhd.c:

     20 struct kset block_subsys;

其实也就是一个struct kset.而这里的kobj_set_kset_s的作用就是让disk对应kobject的kset等于block_subsys.也就是说让kobject找到它的kset.(如果你还记得当初我们在我是Sysfs中分析的kobject和kset的那套理论的话,你不会不明白这里的意图.)而kobject_init()初始化一个kobject,这个函数通常就是出现在设置了kobject的kset之后.
网友”暗恋未遂”打断了我,他说这行代码并不是定义一个结构体.它更像是一个声明,而不像是定义.我仔细一看,似乎真的是的,这里的确是声明,而定义并不在这里,Linux内核代码的确是虚虚实实真真假假,一不小心就会看走眼,写代码的哥们儿果然是深谙兵不厌诈的道理.但愿他们只是借此表达他们对现实社会的不满吧,毕竟在这年头,只有假货是真的,别的都是假的.那么定义在哪里呢?同一个文件中:

    610 decl_subsys(block, &ktype_block, &block_uevent_ops);

这个decl_subsys来自include/linux/kobject.h:

    173 #define decl_subsys(_name,_type,_uevent_ops) /

    174 struct kset _name##_subsys = { /

    175         .kobj = { .name = __stringify(_name) }, /

    176         .ktype = _type, /

    177         .uevent_ops =_uevent_ops, /

    178 }

结合这个宏的定义,我们知道,我们等效于做了下面这么一件事情:

    174 struct kset block_subsys = { /

    175         .kobj = { .name = __stringify(block) }, /

    176         .ktype = &ktype_block, /

    177         .uevent_ops = &block_uevent_ops, /

    178 }

正是因为有了这么一个定义,正是因为这里我们把”block”给了block_subsys的kobj的name成员,所以当我们在block子系统初始化的时候调用subsystem_register(&block_subsys)之后,我们才会在/sys/目录下面看到”block”子目录.

localhost:~ # ls /sys/

block  bus  class  devices  firmware  fs  kernel  module  power

749行,初始化一个工作队列.到时候用到了再来看.
至此,alloc_disk_node就将返回,从而alloc_disk也就返回了.
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: