【linux API分析】module

编程入门 行业动态 更新时间:2024-10-28 08:17:22

【<a href=https://www.elefans.com/category/jswz/34/1770067.html style=linux API分析】module"/>

【linux API分析】module

linux版本:4.19
module_init()与module_exit()用于驱动的加载,分别是驱动的入口与退出函数

  • module_init():内核启动时或动态插入模块时调用
  • module_exit():驱动移除时调用
    本篇文章介绍module_init()

module_init()

module_init()是驱动的入口函数,该函数定义在include\linux\module.h文件

/*** module_init() - driver initialization entry point* @x: function to be run at kernel boot time or module insertion** module_init() will either be called during do_initcalls() (if* builtin) or at module insertion time (if a module).  There can only* be one per module.*/
#define module_init(x)	__initcall(x);

__initcall(x)函数定义在include\linux\init.h文件里面

#define __initcall(fn) device_initcall(fn)

device_initcall(fn)定义也在include\linux\init.h文件里面

#define device_initcall(fn)		__define_initcall(fn, 6)

__define_initcall(fn, 6)定义也在include\linux\init.h文件里面

#define __define_initcall(fn, id) ___define_initcall(fn, id, .initcall##id)

___define_initcall(fn, id, .initcall##id)定义也在include\linux\init.h文件里面

/** 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.** Initcalls are run by placing pointers in initcall sections that the* kernel iterates at runtime. The linker can do dead code / data elimination* and remove that completely, so the initcall sections have to be marked* as KEEP() in the linker script.*/#ifdef CONFIG_HAVE_ARCH_PREL32_RELOCATIONS
#define ___define_initcall(fn, id, __sec)			\__ADDRESSABLE(fn)					\asm(".section	\"" #__sec ".init\", \"a\"	\n"	\"__initcall_" #fn #id ":			\n"	\".long	" #fn " - .			\n"	\".previous					\n");
#else
#define ___define_initcall(fn, id, __sec) \static initcall_t __initcall_##fn##id __used \__attribute__((__section__(#__sec ".init"))) = fn;
#endif

综上module_init调用顺序如下:

module_init()--->__initcall()--->device_initcall()--->__define_initcall()--->___define_initcall()

对___define_initcall()函数进行分析
首先了解一下#与##的作用

符号作用举例
##“##”符号可以是连接的意思例如initcall_##fn##id为initcall_fnid,假设fn为fbmem_init,id=6时,initcall_##fn##id为initcall_fbmem_init6
#"#"符号可以是字符串的意思例如#id为“id”,id=6时,#id为“6”

所以module_init(fbmem_init)函数,相当于

static initcall_t __initcall_fbmem_init6 __used __attribute__((__section__(".initcall6.init"))) =fbmem_init

这行代码定义了一个静态变量__initcall_fbmem_init6,变量类型为initcall_t(是一个函数指针类型,用于表示内核的初始化函数),__used 用于告诉编译器不要将“__initcall_fbmem_Init6”变量视为未使用的变量,避免编译器优化移除它。
attribute((section(“.initcall6.init”))),编译器指令,告诉编译器将“__initcall_fbmem_init6”变量放置在‘.initcall6.init’的代码段中(这个代码段通常用于存放内核的初始化函数,在启动的时候按顺序执行,.initcall1.init、.initcall2.init 。。。)
‘= fbmem_init’ 这将’__initcall_fbmem_init6’初始化为指向‘fbmem_init’函数的指针。
  总之,这段代码的作用是将‘fbmem_init’函数注册为一个初始化函数,使其在内核启动的时候执行。
对于编译成模块,执行sudo insmod的时候,是如何加载的,等我知道后再来写

更多推荐

【linux API分析】module

本文发布于:2023-12-07 15:14:44,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1671525.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:linux   API   module

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!