当前位置: 首页 > news >正文

【linux API分析】module_init

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的时候,是如何加载的,等我知道后再来写

http://www.lryc.cn/news/197019.html

相关文章:

  • NSDT孪生编辑器助力智慧城市
  • 如何优雅的实现接口统一调用
  • tomcat、nginx实现四层转发+七层代理+动静分离实验
  • 交通目标检测-行人车辆检测流量计数 - 计算机竞赛
  • Java Excel转PDF,支持xlsx和xls两种格式, itextpdf【即取即用】
  • 重生奇迹mu宠物带来不一样的体验
  • 【C++笔记】多态的原理、单继承和多继承关系的虚函数表、 override 和 final、抽象类、重载、覆盖(重写)、隐藏(重定义)的对比
  • 安装thinkphp6并使用多应用模式,解决提示路由不存在解决办法
  • FPGA笔试
  • Pytorch:cat、stack、squeeze、unsqueeze的用法
  • 聊聊HttpClient的RedirectStrategy
  • 【1day】复现宏景OA KhFieldTree接口 SQL注入漏洞
  • 同为科技TOWE智能PDU引领数据中心机房远控用电安全高效
  • 支付成功后给指定人员发送微信公众号消息
  • 漏洞复现--安恒明御安全网关文件上传
  • 简单的对称加密
  • vue源码笔记之——响应系统
  • Android Studio Giraffe | 2022.3.1
  • Spring Boot 3.0 已经就绪,您准备好了么?
  • 5+非肿瘤分析,分型+WGCNA+机器学习筛选相关基因
  • 算法课作业2 OJ for Divide and Conquer
  • 申请全国400电话的步骤及注意事项
  • C++ 的设计模式之 工厂方法加单例
  • Deploy、Service与Ingress
  • 定制化推送+精细化运营,Mobpush助力《迷你世界》用户留存率提升23%
  • 深度学习零基础教程
  • 简单测试一下 展锐的 UDX710 性能
  • 一百九十、Hive——Hive刷新分区MSCK REPAIR TABLE
  • 智慧公厕:探索未来城市环境卫生设施建设新标杆
  • 高压放大器在无线电能中应用有哪些