Linux中THIS_MODULE宏定义详解
? ?一直都在耿耿于懷,這個THIS_MODULE到底是個什么玩意,linux內核中無處不在的東西。今天上網搜了一下,算是基本明白了。網上牛人寫的已經比較詳細,另外目前暫時沒有時間往更深層次分析,所以直接貼過來得了。。。
轉帖網址:
http://blog.csdn.net/a954423389/archive/2010/12/27/6101369.aspx
源碼位置:
@ kernel/module.c
@ include/linux/module.h
?
結構體struct module在內核中代表一個內核模塊,通過insmod(實際執行init_module系統調用)把自己編寫的內核模塊插入內核時,模塊便與一個?struct module結構體相關聯,并成為內核的一部分。下面是結構體struct module的完整定義,接下來會逐個解釋:
????struct module
????{
????????enum module_state state;
????????struct list_head list;
????????char name[MODULE_NAME_LEN];
?
????????struct module_kobject mkobj;
????????struct module_param_attrs *param_attrs;
????????const char *version;
????????const char *srcversion;
?
????????const struct kernel_symbol *syms;
????????unsigned int num_syms;
????????const unsigned long *crcs;
?
????????const struct kernel_symbol *gpl_syms;
????????unsigned int num_gpl_syms;
????????const unsigned long *gpl_crcs;
?
????????unsigned int num_exentries;
????????const struct exception_table_entry *extable;
?
????????int (*init)(void);
????????void *module_init;
????????void *module_core;
????????unsigned long init_size, core_size;
????????unsigned long init_text_size, core_text_size;
????????struct mod_arch_specific arch;
????????int unsafe;
????????int license_gplok;
?
#ifdef CONFIG_MODULE_UNLOAD
????????struct module_ref ref[NR_CPUS];
????????struct list_head modules_which_use_me;
????????struct task_struct *waiter;
????????void (*exit)(void);
#endif
?
#ifdef CONFIG_KALLSYMS
????????Elf_Sym *symtab;
????????unsigned long num_symtab;
????????char *strtab;
????????struct module_sect_attrs *sect_attrs;
#endif
????????void *percpu;
????????char *args;
????};
????我們插入一個內核模塊,一般會使用工具insmod,該工具實際上調用了系統調用init_module,在該系統調用函數中,首先調用?load_module,把用戶空間傳入的整個內核模塊文件創建成一個內核模塊,返回一個struct module結構體。內核中便以這個結構體代表這個內核模塊。
????state是模塊當前的狀態。它是一個枚舉型變量,可取的值為:MODULE_STATE_LIVE,MODULE_STATE_COMING,MODULE_STATE_GOING。分別表示模塊當前正常使用中(存活狀態),模塊當前正在被加載,模塊當前正在被卸載。load_module函數中完成模塊的部分創建工作后,把狀態置為MODULE_STATE_COMING,sys_init_module函數中完成模塊的全部初始化工作后(包括把模塊加入全局的模塊列表,調用模塊本身的初始化函數),把模塊狀態置為MODULE_STATE_LIVE,最后,使用rmmod工具卸載模塊時,會調用系統調用delete_module,會把模塊的狀態置為MODULE_STATE_GOING。這是模塊內部維護的一個狀態。
????list是作為一個列表的成員,所有的內核模塊都被維護在一個全局鏈表中,鏈表頭是一個全局變量struct module *modules。任何一個新創建的模塊,都會被加入到這個鏈表的頭部,通過modules->next即可引用到。
????name是模塊的名字,一般會拿模塊文件的文件名作為模塊名。它是這個模塊的一個標識。
????另外,還要介紹一下宏THIS_MODULE,它的定義如下是#define THIS_MODULE (&__this_module),__this_module是一個struct module變量,代表當前模塊,跟current有幾分相似。可以通過THIS_MODULE宏來引用模塊的struct module結構,試試下面的模塊:
????#include <linux/module.h>
?
????MODULE_LICENSE("Dual BSD/GPL");
?
????static int hello_init(void)
????{
????????unsigned int cpu = get_cpu();
????????struct module *mod;
????????printk(KERN_ALERT "this module: %p==%p/n", &__this_module, THIS_MODULE );
????????printk(KERN_ALERT "module state: %d/n", THIS_MODULE->state );
????????printk(KERN_ALERT "module name: %s/n", THIS_MODULE->name );
????????list_for_each_entry(mod, *(&THIS_MODULE->list.prev), list )
????????????????printk(KERN_ALERT "module name: %s/n", mod->name );
????????return 0;
????}
?
????static void hello_exit(void)
????{
????????printk(KERN_ALERT "module state: %d/n", THIS_MODULE->state );
????}
?
????module_init(hello_init);
????module_exit(hello_exit);
?
owner是一個struct module *類型的結構體指針,現在告訴你的是每個struct module結構體在內核里都代表了一個內核模塊,就像十七大里的每個代表都代表了一批人,至于代表了什么人,選他們的人才知道,同樣,每個struct module結構體代表了什么模塊,對它進行初始化的模塊才知道。當然,初始化這個結構不是寫驅動的人該做的事,是在剛才略過的那個從insmod或?modprobe到你驅動的xxx_init函數的曲折過程中做的事。insmod命令執行后,會調用kernel/module.c里的一個系統調用init_module,它會調用load_module函數,將用戶空間傳入的整個內核模塊文件創建成一個內核模塊,并返回一個struct module結構體,從此,內核中便以這個結構體代表這個內核模塊。
再看看THIS_MODULE宏是什么意思,它在include/linux/module.h里的定義是
85 #define THIS_MODULE (&__this_module)
??? 是一個struct module變量,代表當前模塊,與那個著名的current有幾分相似,可以通過THIS_MODULE宏來引用模塊的struct module結構,比如使用THIS_MODULE->state可以獲得當前模塊的狀態。現在你應該明白為啥在那個歲月里,你需要毫不猶豫毫不遲疑的將struct usb_driver結構里的owner設置為THIS_MODULE了吧,這個owner指針指向的就是你的模塊自己。那現在owner咋就說沒就沒了那?這個說來可就話長了,咱就長話短說吧。不知道那個時候你有沒有忘記過初始化owner,反正是很多人都會忘記,大家都把注意力集中到probe、?disconnect等等需要動腦子的角色上面了,這個不需要動腦子,只需要花個幾秒鐘指定一下的owner反倒常常被忽視,這個就是容易得到的往往不去珍惜,不容易得到的往往日日思量著去爭取。于是在2006年的春節前夕,在咱們都無心工作無心學習等著過春節的時候,Greg堅守一線,去掉了?owner,于是千千萬萬個寫usb驅動的人再也不用去時刻謹記初始化owner了。咱們是不用設置owner了,可core里不能不設置,struct usb_driver結構里不是沒有owner了么,可它里面嵌的那個struct device_driver結構里還有啊,設置了它就可以了。于是Greg同時又增加了usb_register_driver()這么一層,usb_register()可以通過將參數指定為THIS_MODULE去調用它,所有的事情都挪到它里面去做。反正usb_register()?也是內聯的,并不會增加調用的開銷。
?
?
其余相關網址,可供參考:
http://hi.baidu.com/_huangshuijing/blog/item/253f9a9516183f0c7bf480c5.html
?
http://www.embedu.org/Column/Column92.htm
?
以下均針對于內核2.6.18
在module.h 中 THIS_MODULE的定義如下:
extern struct module __this_module; #define THIS_MODULE (&__this_module)即是保存了__this_module這個對象的地址,那這個__this_module在哪里定義呢?這就要從module的編譯說起啦,如果編譯過模塊就會發現,會生成*.mod.c這樣的一個文件,打開這個文件,就會發現,類似下面的定義:
struct module __this_module __attribute__((section(".gnu.linkonce.this_module"))) = {.name = KBUILD_MODNAME,.init = init_module, #ifdef CONFIG_MODULE_UNLOAD.exit = cleanup_module, #endif };這個文件是調用modpost生成的,modpost的main中有這樣一段代碼:
for (mod = modules; mod; mod = mod->next) {if (mod->skip)continue;buf.pos = 0;add_header(&buf, mod);add_versions(&buf, mod);add_depends(&buf, mod, modules);add_moddevtable(&buf, mod);add_srcversion(&buf, mod);sprintf(fname, "%s.mod.c", mod->name);write_if_changed(&buf, fname);}其中的add_header就偷偷添加了__this_module 的定義
static void add_header(struct buffer *b, struct module *mod) {buf_printf(b, "#include <linux/module.h>\n");buf_printf(b, "#include <linux/vermagic.h>\n");buf_printf(b, "#include <linux/compiler.h>\n");buf_printf(b, "\n");buf_printf(b, "MODULE_INFO(vermagic, VERMAGIC_STRING);\n");buf_printf(b, "\n");buf_printf(b, "struct module __this_module\n");buf_printf(b, "__attribute__((section(\".gnu.linkonce.this_module\"))) = {\n");buf_printf(b, " .name = KBUILD_MODNAME,\n");if (mod->has_init)buf_printf(b, " .init = init_module,\n");if (mod->has_cleanup)buf_printf(b, "#ifdef CONFIG_MODULE_UNLOAD\n"" .exit = cleanup_module,\n""#endif\n");buf_printf(b, "};\n"); }?
創作挑戰賽新人創作獎勵來咯,堅持創作打卡瓜分現金大獎總結
以上是生活随笔為你收集整理的Linux中THIS_MODULE宏定义详解的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 用c#开发微信 (13) 微统计 - 阅
- 下一篇: 第二次冲刺——第7天