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