一直都在耿耿于怀,这个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
分享到:
相关推荐
结构体struct module在内核中代表一个内核模块,通过insmod(实际执行init_module系统调用)把自己编写的内核模块插入内核时,模块便与一个struct module结构体相关联,并成为内核的一部分。下面是结构体struct module...
NV深度学习EVB,核心板资料 NVIDIA introduced major improvements to performance and power efficiency ... the Pascal GPU architecture continues to improve upon this SM design with the following enhancements
This is the kerberos module authentication implementation in C
This document is about CEH_v5_Module_00_Student_Introduction
This is a book about the bluetooth module.
nodejs开发模块
This is vga test module.
This is the i2c code in verilog.Above the top module of that .
<param name="moduleclass_sfx" type="text" default="" label="Module Class Suffix" description="A suffix to be applied to the css class of the module (table.moduletable), this allows individual module ...
This Module is the Test Bench for AES Algorithm
This repository contains the library and example code to work with our VMA430 - gPS MODULE U-BLOX NEO-7M
PInvoke, C#. This application allow to catch data from the joystick motions and pressed buttons.
三年级上册英语一课一练-Module 6 Unit 2 What's this_外研版(三起)扫描版.doc
名称ngx_http_slowlog_filter_module 该项目仍处于试验阶段,尚处于早期开发阶段。描述ngx_http_slowlog_filter_module -nginx实时监控器模块之一,用于记录超过指定执行... http {...#mark to monitor this locatio
Nginx 发布最新开发版 1.3.14 改进记录: *) Feature: $connections_active, $connections... Thanks to Neal Poole for sponsoring this work. *) Bugfix: in the ngx_http_mp4_module. Thanks to Gernot Vormayr.
This module is for use in VB6 only with DirectX 7.0a or better installed to use Direct Sound. Works with most sound cards. ReadMe file is included and comments have been added to make using the ...
This is an arduino program that can be used to program a bluetooth module set in AT Mode. Pin connections described in the code.
This module contains functions for analysing strings. This .bas worth a look.
This simple case is used to illustrate the effect of shading a single module in a PV array of 11 modules connected in series. -PVarray1 represnt 1 PV module in the array -PVarray2 represnt 10 ...
Add this to your module dependencies and just replace connection strings in the messages.properties file.