内核模块 初始化流程
初始化流程分析及 基于Linux-5.12.4 内核版本。
module_init 与 MODULE
位置:/include/linux/module.h
通过 MODULE 宏,可区分是动态加载或者静态加载。
静态加载:将函数地址 fn 赋值给变量 __initcall_##fn##id。变量存放于段 <N>.init 中。
动态加载:在装载模块时,先在内存中申请空间,再将模块代码拷贝到对应位置并重定位。
MODULE 相关文件
根目录 Makefile:定义 MODULE 的变量
KBUILD_AFLAGS_MODULE := -DMODULE
KBUILD_CFLAGS_MODULE := -DMODULE
----------
scripts/Makefile.lib:使用 KBUILD_CFLAGS_MODULE、KBUILD_CFLAGS_MODULE 变量。根据模块编译参数判断编译哪个。
real-obj-m := $(call real-search, $(obj-m),-objs -y -m)
# Add subdir path
real-obj-m := $(addprefix $(obj)/,$(real-obj-m))
part-of-module = $(if $(filter $(basename $@).o, $(real-obj-m)),y)
# 如果 part-of-module = y,则结果为 $(KBUILD_CFLAGS_MODULE) $(CFLAGS_MODULE),,否则为后者。
modkern_cflags = $(if $(part-of-module), \
$(KBUILD_CFLAGS_MODULE) $(CFLAGS_MODULE), \
$(KBUILD_CFLAGS_KERNEL) $(CFLAGS_KERNEL) $(modfile_flags))
modkern_aflags = $(if $(part-of-module), \
$(KBUILD_AFLAGS_MODULE) $(AFLAGS_MODULE), \
$(KBUILD_AFLAGS_KERNEL) $(AFLAGS_KERNEL))
c_flags = -Wp,-MMD,$(depfile) $(NOSTDINC_FLAGS) $(LINUXINCLUDE) \
-include $(srctree)/include/linux/compiler_types.h \
$(_c_flags) $(modkern_cflags) \
$(basename_flags) $(modname_flags)
a_flags = -Wp,-MMD,$(depfile) $(NOSTDINC_FLAGS) $(LINUXINCLUDE) \
$(_a_flags) $(modkern_aflags)
# scripts/Makefile.modfinal:13:include $(srctree)/scripts/Makefile.lib
# scripts/Makefile.modpost:47:include scripts/Makefile.lib
# scripts/Makefile.build:45:include scripts/Makefile.lib
----------
关联文件:
Makefile.modfinal 引用于:scripts/Makefile.modpost:138: $(Q)$(MAKE) -f $(srctree)/scripts/Makefile.modfinal
Makefile.modpost 引用于:Makefile:<XXX>: $(Q)$(MAKE) -f $(srctree)/scripts/Makefile.modpost
Makefile.build 介绍于:tools/build/Documentation/Build.txt +24。用于源码外编译,即需要指定 srctree 路径。
Linux内核模块编译、加载、运行机制分析、版本控制、许可声明、内核污染、模块传参、模块签名机制、out-of-tree动态模块编译及Makefile模板编写,尽在《Linux内核编程》,详情点击:王利涛老师个人淘宝店:Linux内核编程