加入收藏 | 设为首页 | 会员中心 | 我要投稿 应用网_镇江站长网 (https://www.0511zz.com/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 服务器 > 搭建环境 > Linux > 正文

linux内核md源代码解读 二 md模块初始化 - Linux系统

发布时间:2014-03-24 10:47:50 所属栏目:Linux 来源:站长网
导读:在编译完成linux内核源代码的时候,drivers/md目录下会生成多个ko文件,那么这些内核模块哪一个先加载,哪一个后加载的呢?例如md-mod.ko, raid5.ko, raid10.ko
在编译完成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

(编辑:应用网_镇江站长网)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!