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

下一个函数 ,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 也就返回了 .

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值