歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
您现在的位置: Linux教程網 >> UnixLinux >  >> Linux綜合 >> Linux內核

linux內核md源代碼解讀 二 md模塊初始化

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

Copyright © Linux教程網 All Rights Reserved