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