Linux Kernel Module init 实现分析

Moudle Init 实现

~~~~~~~~~~~


__init & __exit 标记:/include/linux/init.h


原理:
#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的内部问题了。




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值