linux内核奇遇记之md源代码解读之二

linux内核奇遇记之md源代码解读之二
转载请注明出处:http://blog.csdn.net/liumangxiong
在编译完成linux内核源代码的时候,drivers/md目录下会生成多个ko文件,那么这些内核模块哪一个先加载,哪一个后加载的呢?例如md-mod.ko, raid5.ko, raid10.ko,这些模块是一起加载的呢,还是有先后顺序呢?如果熟悉linux内核编程的话,知道有一个request_module函数,这个函数用于请求加载一个模块,但这个函数并不能说明一个模块对另一个模块的依赖关系。准确的信息还是来自于Kconfig,这里只抽取Kconfig中相关的部分:
config BLK_DEV_MD
     tristate "RAID support"
config MD_RAID10
     tristate "RAID-10 (mirrored striping) mode"
     depends on BLK_DEV_MD
config MD_RAID456
     tristate "RAID-4/RAID-5/RAID-6 mode"
     depends on BLK_DEV_MD
从这里我们可以看出,raid5.ko, raid10.ko都是依赖于md-mod.ko的,这就决定了我们的阅读方向是从md-mod.ko中开始的。
那么md-mod.ko中又是从哪个文件开始的呢?这就要找module_init函数,这个函数在md.c中定义的,那么就从这里入手。
8416 static int __init md_init(void)
8417 {
8418         int ret = -ENOMEM;
8419 
8420         md_wq = alloc_workqueue("md", WQ_MEM_RECLAIM, 0);
8421         if (!md_wq)
8422                 goto err_wq;
8423 
8424         md_misc_wq = alloc_workqueue("md_misc", 0, 0);
8425         if (!md_misc_wq)
8426                 goto err_misc_wq;
8427 
8428         if ((ret = register_blkdev(MD_MAJOR, "md")) < 0)
8429                 goto err_md;
8430 
8431         if ((ret = register_blkdev(0, "mdp")) < 0)
8432                 goto err_mdp;
8433         mdp_major = ret;
8434 
8435         blk_register_region(MKDEV(MD_MAJOR, 0), 1UL<<MINORBITS, THIS_MODULE,
8436                             md_probe, NULL, NULL);
8437         blk_register_region(MKDEV(mdp_major, 0), 1UL<<MINORBITS, THIS_MODULE,
8438                             md_probe, NULL, NULL);
8439 
8440         register_reboot_notifier(&md_notifier);
8441         raid_table_header = register_sysctl_table(raid_root_table);
8442 
8443         md_geninit();
8444         return 0;
8445 
8446 err_mdp:
8447         unregister_blkdev(MD_MAJOR, "md");
8448 err_md:
8449         destroy_workqueue(md_misc_wq);
8450 err_misc_wq:
8451         destroy_workqueue(md_wq);
8452 err_wq:
8453         return ret;
8454 }
模块的初始化过程看起来异常地简单,这就像有些人表面看起来十分普通,内心里却无比地强大,所以不要只看外表,还要听其言观其行。内在的美丽比外表的荣华更具吸引力和持久性。
8420和8424行,分别创建了工作队列,md_wq是用于flush命令的,另一个md_misc_wq,misc是miscellaneous的简写,是杂项的意思,用于处理一些零零碎碎的事情。
8428和8431行,创建了两个块设备,刚开始我只注意md的设备,压根没在意mdp,搜索变量mdp_major,在函数autorun_devices中使用了这个变量:
5474                 if (part) {
5475                         dev = MKDEV(mdp_major,
5476                                     rdev0->preferred_minor << MdpMinorShift);
5477                         unit = MINOR(dev) >> MdpMinorShift;
5478                 } else {
5479                         dev = MKDEV(MD_MAJOR, rdev0->preferred_minor);
5480                         unit = MINOR(dev);
5481                 }
5474行,变量part是函数传入参数,表示磁盘第几个分区,那么就知道mdp_major中字母p是表示part的意思,而mdp_major就表示用磁盘分区创建的阵列。
8435和8437行,创建了两个region,这两个函数的作用是在用户态创建了一个/dev/md*设备时,内核态就会对应调用md_probe创建一个mddev结构体,之后在用户态对/dev/md*的操作到内核态就相应地对mddev的操作了。
8440行,注册关机回调函数,主要作用是停止阵列线程,刷数据操作。
8441行,注册sysctl函数,用于控制阵列最小和最大的sync速度。
8443行,注册proc函数,于是有了目录/proc/mdstat,该目录的显示由函数md_seq_show控制。
md初始化代码就这样轻松地完成了,可是回到我们的初衷,仍然对md设备一无所知。那么md设备是如何创建的呢?创建的过程又是怎么的呢?一个阵列拥有哪些资源?下一节我们直入核心,开始阅读阵列创建的过程。
转载请注明出处:http://blog.csdn.net/liumangxiong

你可能感兴趣的:(linux内核奇遇记之md源代码解读之二)