内核模块 module_init

一个模块加载到内核后,运行和退出,是通过模块的出入口module_init/module_exit来完成的。

module_init/module_exit:注册 & 注销

int __init init_func(void);
    被 __init 声明、module_init 指定的入口函数
    模块被加载到内核时,入口函数自动被内核执行
    返回 errno。应用层可根据返回值,使用 perror 进行解析
void __exit exit_func(void);
    被 __exit 声明、module_exit 指定的退出函数
    模块卸载函数,模块卸载时该函数自动被内核执行
    主要完成结束模块运行的相关工作、清理各种资源

--------------------
module_init(init_func);
    加载模块时被调用,__define_initcall 的封装
subsys_initcall(init_func);
    加载模块时被调用,优于 module_init 执行
module_exit(exit_func);
    卸载模块时被调用

内核中的模块初始化入口等级

宏名            调用次数            优先级
----------------------------------------
pure_initcall       9               0
core_initcall       206             1
postcore_initcall   143             2
arch_initcall       474             3
subsys_initcall     689             4
fs_initcall         122             5
rootfs_initcall     8           rootfs
device_initcall     389             6
late_initcall       246             7
module_init         3158        Loadable or 6

内核释放初始化段所占内存

__init & __exit:本质是将 初始化/退出 代码放入 .init.text/.exit.text 段中。
                 __init 在执行完后释放,__exit 暂不讨论。
    #define __init __section(.init.text) __cold __latent_entropy __noinitretpoline
    #define __exit __section(.exit.text) __exitused __cold notrace
ftrace_free_init_mem:内存追踪相关。
free_initmem:释放初始化时指定的空间。
              要释放的首末地址初始化于 vmlinux.lds.S,包含 .init* 段。地址都是对齐过的。
              不同架构的释放过程类似。
              arm64 直接就为 free_reserved_area,其他架构也最终调用页的释放函数。
Linux内核模块编译、加载、运行机制分析、版本控制、许可声明、内核污染、模块传参、模块签名机制、out-of-tree动态模块编译及Makefile模板编写,尽在《Linux内核编程》,详情点击:王利涛老师个人淘宝店:Linux内核编程