Linux内核延迟调用函数late_initcall()

本文详细探讨了Linux内核中的`late_initcall`函数,它用于标记那些在系统初始化后期调用的函数,优先级低于`module_init`。`late_initcall`放在.initcall7.init段,确保依赖于其他设备的驱动在适当时候加载。文章解释了初始化内存分布、`late_initcall`与`module_init`的区别,以及它们在内核加载过程中的顺序。
摘要由CSDN通过智能技术生成
static int __init chg_init(void)
{
	return platform_driver_register(&charger_driver);
}

static void __exit chg_exit(void)
{
	platform_driver_unregister(&charger_driver);
}
late_initcall(chg_init);
module_exit(chg_exit);

MODULE_DESCRIPTION("Dummy Charger driver");
MODULE_LICENSE("GPL");

late_initcall

init的初始化内存分布

vmlinux.lds文件用来决定初始化所用的内存的分布
内存的分布可以用下图来说明:

在这里插入图片描述

__init用来标示的是初始化函数,在初始化后不会再调用
__initdata是初始化数据
__initparam是初始化参数,其他7个初始化宏就是初始化函数会用到的。
所有标示为__init的函数都会在链接的时候都会放在.init.text中,放得顺序是不确定的,与编译、链接顺序有关
同时所有__init函数都会在.initcallx.init中放一个函数指针,初始化的时候按照.initcall1.init->.initcall7.init的顺序初始化,.initcallx.init有不同的别名,在init.h中定义

late_initcall的定义

include\linux\init.h
在这里插入图片描述

在include\linux\init.h 可以看到 late_initcall 的定义,是放在了 .initcall7.init中,即第7个段。
而常言的module_init 是定义为了 device_initcall,即放在了第6个段中。
__define_initcall 在这里就不展开了,详情可以先看:
https://blog.csdn.net/weixin_47491758/article/details/125775025

late_initcall 和 module_init 的区别

前面有提到,module_init 的放在于第6个段执行,
而 late_initcall 是放在第7个段执行,
所以 late_initcall 的优先级最低,是最后执行的。
这里就涉及到了设备之间的依赖关系。

个人认为,使用 late_initcall 可以保证具有依赖关系的设备,可以先等依赖设备先加载好,再去加载该设备。
例如B设备的加载要依赖A设备,可以让A设备用 module_init加载,B设备使用late_initcall 加载。

参考

https://blog.csdn.net/Ivan804638781/article/details/88419376
https://blog.csdn.net/qq_39491794/article/details/80412630



驱动开发基础 -- module_init() 和 late_initcall() 的加载顺序

在模块加载的过程中,init头文件非常重要,它定义了module_init和xxx_initcall以及相应的

clearup函数,还决定了模块的加载顺序级别以及模块编译进内核和动态加载时module_init所做的不同的事情。

       而vmlinux.lds文件用来决定初始化所用的内存的分布,我们看看内核初始化的内存分布:

 
  1. .init.text : {

  2. _sinittext = .;

  3. *(.init.text)

  4. _einittext = .;

  5. }

  6. .init.data : {

  7. *(.init.data);

  8. __vtop_table_begin = .;

  9. *(.vtop_fixup);

  10. __vtop_table_end = .;

  11. __ptov_table_begin = .;

  12. *(.ptov_fixup);

  13. __ptov_table_end = .;

  14. }

  15. . = ALIGN(16);

  16. __setup_start = .;

  17. .init.setup : { *(.init.setup) }

  18. __setup_end = .;

  19. __initcall_start = .;

  20. .initcall.init : {

  21. *(.initcall1.init)

  22. *(.initcall2.init)

  23. *(.initcall3.init)

  24. *(.initcall4.init)

  25. *(.initcall5.init)

  26. *(.initcall6.init)

  27. *(.initcall7.init)

  28. }

  29. __initcall_end = .;

内存的分布可以用下图来说明:

           

  

       其中__init用来标示的是初始化函数,在初始化后不会再调用,__initdata是初始化数据, __initparam是初始化参数,其他7个初始化宏就是初始化函数会用到的。所有标示为__init的函数都会在链接的时候都会放在.init.text中,放得顺序是不确定的,与编译、链接顺序有关,同时所有__init函数都会在.initcallx.init中放一个函数指针,初始化的时候按照.initcall1.init->.initcall7.init的顺序初始化,.initcallx.init有不同的别名,在init.h中定义:

       以下的定义是built-in的定义,即将模

  • 1
    点赞
  • 28
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值