Linux内核如何加载编译进内核的模块

在Linux内核启动过程中,在init()函数执行过程中会调用do_basic_setup函数,进程调用 do_initcalls()函数,该函数实现如下:

451 static void __init do_initcalls(void)
452 {
453         initcall_t *call;
454 
455         call = &__initcall_start;
456         do {
457                 (*call)();
458                 call++;
459         } while (call < &__initcall_end);
460 
461         /* Make sure there is no pending stuff from the initcall sequence */
462         flush_scheduled_tasks();
463 }

其中,__initcall_start是段.initcall.init的起始地址,由链接脚本在编译内核时确定,而对于模块中的module_init有:

 84 #define __init_call     __attribute_used__ __attribute__ ((__section__ (".initcall.init")))
 85 #define __exit_call     __attribute_used__ __attribute__ ((__section__ (".exitcall.exit")))
...
49 typedef int (*initcall_t)(void);
 50 typedef void (*exitcall_t)(void);
 51 
 52 extern initcall_t __initcall_start, __initcall_end;
 53 
 54 #define __initcall(fn)                                                          \
 55         static initcall_t __initcall_##fn __attribute_used__ __init_call = fn
 56 #define __exitcall(fn)                                                          \
 57         static exitcall_t __exitcall_##fn __exit_call = fn
...
102 #define module_init(x)  __initcall(x);

可见,module_init是把定义的函数通过gcc拓展属性attribute,把函数放在了 section (“.initcall.init”))中。
而do_initcalls对该段中存放的每一个函数都通过函数指针initcall_t *call来指向,并通过(*call)()执行。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值