1. 程式人生 > >MODULE_DEVICE_TABLE巨集的作用(轉)

MODULE_DEVICE_TABLE巨集的作用(轉)

1. MODULE_DEVICE_TABLE (usb, skel_table);
該巨集生成一個名為__mod_pci_device_table的區域性變數,該變數指向第二個引數。核心構建時,depmod程式會在所有模組中搜索符號__mod_pci_device_table,把資料(裝置列表)從模組中抽出,新增到對映檔案/lib/modules/KERNEL_VERSION/modules.pcimap中,當depmod結束之後,所有的PCI裝置連同他們的模組名字都被該檔案列出。當核心告知熱插拔系統一個新的PCI裝置被發現時,熱插拔系統使用modules.pcimap檔案來找尋恰當的驅動程式。

 

MODULE_DEVICE_TABLE的第一個引數是裝置的型別,如果是USB裝置,那自然是usb(如果是PCI裝置,那將是pci,這兩個子系統用同一個巨集來註冊所支援的裝置)。後面一個引數是裝置表,這個裝置表的最後一個元素是空的,用於標識結束。例:假如程式碼定義了USB_SKEL_VENDOR_ID是 0xfff0,USB_SKEL_PRODUCT_ID是0xfff0,也就是說,當有一個裝置接到集線器時,usb子系統就會檢查這個裝置的 vendor ID和product ID,如果他們的值是0xfff0時,那麼子系統就會呼叫這個模組作為裝置的驅動。


1、MODULE_DEVICE_TABLE
(mdio, realtek_tbl);
    該巨集定義在檔案中,原型為:

點選(此處)摺疊或開啟

  1. #define MODULE_GENERIC_TABLE(gtype,name)            \
  2. extern const struct gtype##_id __mod_##gtype##_table        \

  3.   __attribute__ ((unused, alias(__stringify(name))))
  4.   
  5. #define MODULE_DEVICE_TABLE(type,name)        \
  6.   MODULE_GENERIC_TABLE(type##_device,name)

    生成一個名為__mod_mdio_device_id_table,核心構建時,depmod程式會在所有模組中搜索符號__mod_mdio_device_id_table,把資料(裝置列表)從模組中抽出,新增到對映檔案 /lib/modules/KERNEL_VERSION/modules.pcimap 中,當depmod結束之後,所有的MDIO裝置連同他們的模組名字都被該檔案列出。在需要驅動的時候,由modules.pcimap檔案來找尋恰當的驅動程式。
    MODULE_DEVICE_TABLE的第一個引數是裝置的型別,如果是PHY裝置,那自然是MDIO(如果是PCI裝置,那將是pci,這兩個子系統用同一個巨集來註冊所支援的裝置)。後面一個引數是裝置表,這個裝置表的最後一個元素是空的,用於標識結束。ex:
    

點選(此處)摺疊或開啟

  1. static struct mdio_device_id __maybe_unused realtek_tbl[] = {
  2.     { 0x001cc912, 0x001fffff },
  3.     { }
  4. };

2、其他相關巨集的定義

這些巨集定義在下
1) MODULE_AUTHOR(name) 定義驅動的程式設計者,name為string
2) MODULE_LIC ENSE(license) 定義驅動的license,一般為GPL,或相關公司的license
3) MODULE_DESCRIPT ION(desc) 對驅動程式的描述,string
4) MODULE_SUPPORTED_DEVICE(name) 驅動程式所支援的裝置,string
5) MODULE_PARM(var,type),提供在執行時通過控制檯將引數傳遞給模組(在insmod時)。如果我們想用這個巨集來傳遞命令列引數,那麼在我們的模組中定義一個全域性變數。在insmod模組時,便可以用引數的形式,將具體的實參傳遞給模組中的那個全域性變數。MODULE_PARM(name,type)有兩個引數,一個是這個全域性變數的名稱,另一個是這個全域性變數的型別。而他的型別有以下幾種:
    b:位元型
    h:短整型
    i:整型
    l:長整型
    s:字串型
在傳遞字串型的引數時,這個全域性變數需要在模組中用Char *來宣告!insmod會自動為其分配記憶體空間。
例如: 

點選(此處)摺疊或開啟

  1. int a = 3;
  2. char *st;
  3. MODULE_PARM(a,”i”);
  4. MODULE_PARM(st,”s”);

在insmod是我們加這樣的引數:

點選(此處)摺疊或開啟

  1. insmode a.o “a = 3″, “st = hello world”

    這裡最重要的是,MODULE_PARM()也支援我們最常用的陣列型別。用短線‘-’把兩個數字分開,分別表示陣列引數中的最小位數和最大位數。例如: 

點選(此處)摺疊或開啟

  1. int array[8];
  2. MODULE_PARM(array,”1-8i”);

在命令列我們使用加這樣的引數: 

點選(此處)摺疊或開啟

  1. insmod a.o “array = 38745,123,4000″

    在那些模組程式設計時,我們往往給這些全域性變數以預設值,如果我們才insmod時沒有傳入引數時,模組會使用這些預設值,而如果我們傳入引數時,這些預設值便被覆蓋掉。
6) MODULE_PARM_DESC(var,desc) 對變數的描述
7) GP L_HEADER()
8) THI S_M ODULE 指向全域性變數 __this_module (struct module)的指標。
9)系統對每個模組維護一個usage counter,以便決定何時可以安全的解除安裝模組。
    下面的巨集用來對該usage counter操作,usage counter可以通過/proc/modules檔案檢視
    MOD_INC_USE_COUNT
    MOD_DEC_USE_COUNT
    MOD_IN_USE
    MODULE_DEVICE_TABLE
10) EXPORT_SYMTAB 預處理巨集,當在程式中用EXPORT_SYMBOL等巨集時需要定義該巨集。例如,可以在Makefile中定義:-DEXPORT_SYMTAB
__EXPORT_SYMBOL(sym,str)
EXPORT_SYMBOL(var)
11) EXPORT_SYMBOL_NOVERS(var) 匯出一個符合到核心符號表,匯出後,該符合可以供其他模組使用。這個巨集有助於編寫驅動程式時清楚的劃分出層次。可以通過/proc/ksyms檔案或ksyms命令檢視核心符號表。EXPORT_SYMBOL_NOVERS(var),匯出是不帶版本資訊。在使用該巨集時,需定義 EXPORT_SYMBOL_GPL(var)
12) EXPORT_NO_SYMBOLS 顯示指出,該模組不向核心符合表匯出符號
13)SET_MODULE_OWNER