在編譯完成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