Linux中THIS_MODULE宏定义详解
? ?一直都在耿耿于懷,這個THIS_MODULE到底是個什么玩意,linux內(nèi)核中無處不在的東西。今天上網(wǎng)搜了一下,算是基本明白了。網(wǎng)上牛人寫的已經(jīng)比較詳細,另外目前暫時沒有時間往更深層次分析,所以直接貼過來得了。。。
轉(zhuǎn)帖網(wǎng)址:
http://blog.csdn.net/a954423389/archive/2010/12/27/6101369.aspx
源碼位置:
@ kernel/module.c
@ include/linux/module.h
?
結(jié)構(gòu)體struct module在內(nèi)核中代表一個內(nèi)核模塊,通過insmod(實際執(zhí)行init_module系統(tǒng)調(diào)用)把自己編寫的內(nèi)核模塊插入內(nèi)核時,模塊便與一個?struct module結(jié)構(gòu)體相關(guān)聯(lián),并成為內(nèi)核的一部分。下面是結(jié)構(gòu)體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;
????};
????我們插入一個內(nèi)核模塊,一般會使用工具insmod,該工具實際上調(diào)用了系統(tǒng)調(diào)用init_module,在該系統(tǒng)調(diào)用函數(shù)中,首先調(diào)用?load_module,把用戶空間傳入的整個內(nèi)核模塊文件創(chuàng)建成一個內(nèi)核模塊,返回一個struct module結(jié)構(gòu)體。內(nèi)核中便以這個結(jié)構(gòu)體代表這個內(nèi)核模塊。
????state是模塊當(dāng)前的狀態(tài)。它是一個枚舉型變量,可取的值為:MODULE_STATE_LIVE,MODULE_STATE_COMING,MODULE_STATE_GOING。分別表示模塊當(dāng)前正常使用中(存活狀態(tài)),模塊當(dāng)前正在被加載,模塊當(dāng)前正在被卸載。load_module函數(shù)中完成模塊的部分創(chuàng)建工作后,把狀態(tài)置為MODULE_STATE_COMING,sys_init_module函數(shù)中完成模塊的全部初始化工作后(包括把模塊加入全局的模塊列表,調(diào)用模塊本身的初始化函數(shù)),把模塊狀態(tài)置為MODULE_STATE_LIVE,最后,使用rmmod工具卸載模塊時,會調(diào)用系統(tǒng)調(diào)用delete_module,會把模塊的狀態(tài)置為MODULE_STATE_GOING。這是模塊內(nèi)部維護的一個狀態(tài)。
????list是作為一個列表的成員,所有的內(nèi)核模塊都被維護在一個全局鏈表中,鏈表頭是一個全局變量struct module *modules。任何一個新創(chuàng)建的模塊,都會被加入到這個鏈表的頭部,通過modules->next即可引用到。
????name是模塊的名字,一般會拿模塊文件的文件名作為模塊名。它是這個模塊的一個標(biāo)識。
????另外,還要介紹一下宏THIS_MODULE,它的定義如下是#define THIS_MODULE (&__this_module),__this_module是一個struct module變量,代表當(dāng)前模塊,跟current有幾分相似。可以通過THIS_MODULE宏來引用模塊的struct module結(jié)構(gòu),試試下面的模塊:
????#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 *類型的結(jié)構(gòu)體指針,現(xiàn)在告訴你的是每個struct module結(jié)構(gòu)體在內(nèi)核里都代表了一個內(nèi)核模塊,就像十七大里的每個代表都代表了一批人,至于代表了什么人,選他們的人才知道,同樣,每個struct module結(jié)構(gòu)體代表了什么模塊,對它進行初始化的模塊才知道。當(dāng)然,初始化這個結(jié)構(gòu)不是寫驅(qū)動的人該做的事,是在剛才略過的那個從insmod或?modprobe到你驅(qū)動的xxx_init函數(shù)的曲折過程中做的事。insmod命令執(zhí)行后,會調(diào)用kernel/module.c里的一個系統(tǒng)調(diào)用init_module,它會調(diào)用load_module函數(shù),將用戶空間傳入的整個內(nèi)核模塊文件創(chuàng)建成一個內(nèi)核模塊,并返回一個struct module結(jié)構(gòu)體,從此,內(nèi)核中便以這個結(jié)構(gòu)體代表這個內(nèi)核模塊。
再看看THIS_MODULE宏是什么意思,它在include/linux/module.h里的定義是
85 #define THIS_MODULE (&__this_module)
??? 是一個struct module變量,代表當(dāng)前模塊,與那個著名的current有幾分相似,可以通過THIS_MODULE宏來引用模塊的struct module結(jié)構(gòu),比如使用THIS_MODULE->state可以獲得當(dāng)前模塊的狀態(tài)。現(xiàn)在你應(yīng)該明白為啥在那個歲月里,你需要毫不猶豫毫不遲疑的將struct usb_driver結(jié)構(gòu)里的owner設(shè)置為THIS_MODULE了吧,這個owner指針指向的就是你的模塊自己。那現(xiàn)在owner咋就說沒就沒了那?這個說來可就話長了,咱就長話短說吧。不知道那個時候你有沒有忘記過初始化owner,反正是很多人都會忘記,大家都把注意力集中到probe、?disconnect等等需要動腦子的角色上面了,這個不需要動腦子,只需要花個幾秒鐘指定一下的owner反倒常常被忽視,這個就是容易得到的往往不去珍惜,不容易得到的往往日日思量著去爭取。于是在2006年的春節(jié)前夕,在咱們都無心工作無心學(xué)習(xí)等著過春節(jié)的時候,Greg堅守一線,去掉了?owner,于是千千萬萬個寫usb驅(qū)動的人再也不用去時刻謹記初始化owner了。咱們是不用設(shè)置owner了,可core里不能不設(shè)置,struct usb_driver結(jié)構(gòu)里不是沒有owner了么,可它里面嵌的那個struct device_driver結(jié)構(gòu)里還有啊,設(shè)置了它就可以了。于是Greg同時又增加了usb_register_driver()這么一層,usb_register()可以通過將參數(shù)指定為THIS_MODULE去調(diào)用它,所有的事情都挪到它里面去做。反正usb_register()?也是內(nèi)聯(lián)的,并不會增加調(diào)用的開銷。
?
?
其余相關(guān)網(wǎng)址,可供參考:
http://hi.baidu.com/_huangshuijing/blog/item/253f9a9516183f0c7bf480c5.html
?
http://www.embedu.org/Column/Column92.htm
?
以下均針對于內(nèi)核2.6.18
在module.h 中 THIS_MODULE的定義如下:
extern struct module __this_module; #define THIS_MODULE (&__this_module)即是保存了__this_module這個對象的地址,那這個__this_module在哪里定義呢?這就要從module的編譯說起啦,如果編譯過模塊就會發(fā)現(xiàn),會生成*.mod.c這樣的一個文件,打開這個文件,就會發(fā)現(xiàn),類似下面的定義:
struct module __this_module __attribute__((section(".gnu.linkonce.this_module"))) = {.name = KBUILD_MODNAME,.init = init_module, #ifdef CONFIG_MODULE_UNLOAD.exit = cleanup_module, #endif };這個文件是調(diào)用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"); }?
創(chuàng)作挑戰(zhàn)賽新人創(chuàng)作獎勵來咯,堅持創(chuàng)作打卡瓜分現(xiàn)金大獎總結(jié)
以上是生活随笔為你收集整理的Linux中THIS_MODULE宏定义详解的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 用c#开发微信 (13) 微统计 - 阅
- 下一篇: [Linux] Linux指令汇总(持续