Moudle Init 实现
原理:
#define __init __section(.init.text) __cold notrace //看看__seciton()就了然了
#define __exit __section(.exit.text) __exitused __cold notrace
# define __section(S) __attribute__ ((__section__(#S))) //__section__为 GNU C 扩展,告诉编译器编译时将这段代码放到S处
用法:
* You should add __init immediately before the function name, like:
*
* static void __init initme(int x, int y)
* {
* extern int z; z = x * y;
* }
*
* If the function has a prototype somewhere, you can also add
* __init between closing brace of the prototype and semicolon:
*
* extern int initialize_foobar_device(int, int, int) __init;
相关其他:
* For initialized data:
* You should insert __initdata between the variable name and equal
* sign followed by value, e.g.:
*
* static int init_variable __initdata = 0;
* static const char linux_logo[] __initconst = { 0x32, 0x36, ... };
module_init() & module_exit()
#define module_init(x) __initcall(x); //和__init一样,也是将其加入到内核映像的".initcall"区,如下:
#define device_initcall(fn) __define_initcall("6",fn,6)
#define __define_initcall(level,fn,id) \
static initcall_t __initcall_##fn##id __used \
__attribute__((__section__(".initcall" level ".init"))) = fn
注释:
/* initcalls are now grouped by functionality into separate
* subsections. Ordering inside the subsections is determined
* by link order.
* For backwards compatibility, initcall() puts the call in
* the device init subsection.
*
* The `id' arg to __define_initcall() is needed so that multiple initcalls
* can point at the same handler without causing duplicate-symbol build errors.
* level 表示优先级,越小越先加载,具体有哪些看源码吧
*/
#define module_exit(x) __exitcall(x); //不在赘述
到这里,就可以顺利编译你的Module了,然就是重要一步: insmod xx
insmod会根据以上编译扩展项的指示:将*.ko中init函数代码加入到内核区域的.init.text,将函数地址放入区域.initcall
内核这样做的目的是便于统一管理module 的内存,因为init函数只会在动态或kernel启动时才会掉用到,一次用完内存就将其释放,节省系统开支。
且看:insmod的实现,module.h module.c
struct module
{
/* ..... */
/* Member of list of modules */
struct list_head list; //Kernel特有的链表结构
/* Startup function. */
int (*init)(void); //这就是了
/* Destruction function. */
void (*exit)(void); //这就是了
/* ..... */
};
insmod syscall:
//kernel/module.c
/* This is where the real work happens */
SYSCALL_DEFINE3(init_module, void __user *, umod,
unsigned long, len, const char __user *, uargs)
{
//函数有点长,简单介绍一下重点吧
/* Do all the hard work */
/* 一个做苦力的孩子。为module分配内存、检查module名、检查export&import symbols
* 找到sections,将各sections加载到指定位置、加载symbols、
mod = load_module(umod, len, uargs);
/* ...... */
/* Start the module */
/* 调用module中的init函数 */
if (mod->init != NULL)
ret = do_one_initcall(mod->init); //init就是module定义的init函数在.initcall中的地址了
/* ...... */
/* init用完了,该释放空间了,能省点就省点 */
module_free(mod, mod->module_init);
/* ...... */
}
~~~~~~~~~~~
原理:
#define __init __section(.init.text) __cold notrace //看看__seciton()就了然了
#define __exit __section(.exit.text) __exitused __cold notrace
# define __section(S) __attribute__ ((__section__(#S))) //__section__为 GNU C 扩展,告诉编译器编译时将这段代码放到S处
用法:
* You should add __init immediately before the function name, like:
*
* static void __init initme(int x, int y)
* {
* extern int z; z = x * y;
* }
*
* If the function has a prototype somewhere, you can also add
* __init between closing brace of the prototype and semicolon:
*
* extern int initialize_foobar_device(int, int, int) __init;
相关其他:
* For initialized data:
* You should insert __initdata between the variable name and equal
* sign followed by value, e.g.:
*
* static int init_variable __initdata = 0;
* static const char linux_logo[] __initconst = { 0x32, 0x36, ... };
module_init() & module_exit()
#define module_init(x) __initcall(x); //和__init一样,也是将其加入到内核映像的".initcall"区,如下:
#define device_initcall(fn) __define_initcall("6",fn,6)
#define __define_initcall(level,fn,id) \
static initcall_t __initcall_##fn##id __used \
__attribute__((__section__(".initcall" level ".init"))) = fn
注释:
/* initcalls are now grouped by functionality into separate
* subsections. Ordering inside the subsections is determined
* by link order.
* For backwards compatibility, initcall() puts the call in
* the device init subsection.
*
* The `id' arg to __define_initcall() is needed so that multiple initcalls
* can point at the same handler without causing duplicate-symbol build errors.
* level 表示优先级,越小越先加载,具体有哪些看源码吧
*/
#define module_exit(x) __exitcall(x); //不在赘述
到这里,就可以顺利编译你的Module了,然就是重要一步: insmod xx
insmod会根据以上编译扩展项的指示:将*.ko中init函数代码加入到内核区域的.init.text,将函数地址放入区域.initcall
内核这样做的目的是便于统一管理module 的内存,因为init函数只会在动态或kernel启动时才会掉用到,一次用完内存就将其释放,节省系统开支。
且看:insmod的实现,module.h module.c
struct module
{
/* ..... */
/* Member of list of modules */
struct list_head list; //Kernel特有的链表结构
/* Startup function. */
int (*init)(void); //这就是了
/* Destruction function. */
void (*exit)(void); //这就是了
/* ..... */
};
insmod syscall:
//kernel/module.c
/* This is where the real work happens */
SYSCALL_DEFINE3(init_module, void __user *, umod,
unsigned long, len, const char __user *, uargs)
{
//函数有点长,简单介绍一下重点吧
/* Do all the hard work */
/* 一个做苦力的孩子。为module分配内存、检查module名、检查export&import symbols
* 找到sections,将各sections加载到指定位置、加载symbols、
mod = load_module(umod, len, uargs);
/* ...... */
/* Start the module */
/* 调用module中的init函数 */
if (mod->init != NULL)
ret = do_one_initcall(mod->init); //init就是module定义的init函数在.initcall中的地址了
/* ...... */
/* init用完了,该释放空间了,能省点就省点 */
module_free(mod, mod->module_init);
/* ...... */
}
好了,module也加载好了,后面就是module的内部问题了。