module_init subsys_initcall与late_initcall的区别

本文深入探讨了Linux内核中各类初始化函数的作用与优先级,包括early_initcall、core_initcall、device_initcall等,并解释了它们在系统启动过程中的执行顺序与重要性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

kernel-4.4\include\linux\init.h

#define pure_initcall(fn)		__define_initcall(fn, 0)
#define core_initcall(fn)		__define_initcall(fn, 1)
#define core_initcall_sync(fn)		__define_initcall(fn, 1s)
#define postcore_initcall(fn)		__define_initcall(fn, 2)
#define postcore_initcall_sync(fn)	__define_initcall(fn, 2s)
#define arch_initcall(fn)		__define_initcall(fn, 3)
#define arch_initcall_sync(fn)		__define_initcall(fn, 3s)
#define subsys_initcall(fn)		__define_initcall(fn, 4)
#define subsys_initcall_sync(fn)	__define_initcall(fn, 4s)
#define fs_initcall(fn)			__define_initcall(fn, 5)
#define fs_initcall_sync(fn)		__define_initcall(fn, 5s)
#define rootfs_initcall(fn)		__define_initcall(fn, rootfs)
#define device_initcall(fn)		__define_initcall(fn, 6)
#define device_initcall_sync(fn)	__define_initcall(fn, 6s)
#define late_initcall(fn)		__define_initcall(fn, 7)
#define late_initcall_sync(fn)		__define_initcall(fn, 7s)

#define __initcall(fn) device_initcall(fn)
kernel-4.4\include\linux\module.h

#define early_initcall(fn)		module_init(fn)
#define core_initcall(fn)		module_init(fn)
#define core_initcall_sync(fn)		module_init(fn)
#define postcore_initcall(fn)		module_init(fn)
#define postcore_initcall_sync(fn)	module_init(fn)
#define arch_initcall(fn)		module_init(fn)
#define subsys_initcall(fn)		module_init(fn)
#define subsys_initcall_sync(fn)	module_init(fn)
#define fs_initcall(fn)			module_init(fn)
#define fs_initcall_sync(fn)		module_init(fn)
#define rootfs_initcall(fn)		module_init(fn)
#define device_initcall(fn)		module_init(fn)
#define device_initcall_sync(fn)	module_init(fn)
#define late_initcall(fn)		module_init(fn)
#define late_initcall_sync(fn)		module_init(fn)

#define console_initcall(fn)		module_init(fn)
#define security_initcall(fn)		module_init(fn)


/**
 * 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);

module_init优先级为6,subsys_init优先级为5,late_init优先级为7.linux数值越小,优先级越高。
在调试过程中,probe函数在系统启动初始化加载时,优先级高的log日记打印容易丢失,为了方便调试测试,可以先调用late_init函数。

<think>好的,我现在需要帮助用户了解Linux内核模块中module_initlate_initcall的用法及区别。首先,我要回忆一下内核初始化的相关知识。记得内核模块的初始化函数是通过宏来定义的,这些宏决定了函数在内核启动过程中的调用顺序。 用户问的是module_initlate_initcall,所以需要明确这两者的不同之处。可能还有其他类似的宏,比如__initcall,但用户主要关注这两个。首先,我应该解释每个宏的基本用法,然后比较它们的执行顺序和用途差异。 我记得内核的初始化分为多个阶段,不同的初始化宏对应不同的优先级。module_init通常用于设备驱动,而late_initcall可能用于那些需要在内核初始化后期执行的模块。需要确认这一点是否正确。例如,module_init对应的初始化级别可能比late_initcall更早,或者更晚? 接下来,我需要查阅内核源码中的相关信息,或者参考内核文档。比如,在include/linux/init.h中,定义了不同级别的初始化宏,如core_initcall、postcore_initcall、arch_initcallsubsys_initcall、fs_initcall、device_initcalllate_initcall等,它们的顺序是依次递增的,即优先级依次降低。而module_init宏会根据模块是否内置到内核还是作为可加载模块来区分:如果是内置的,它等同于device_initcall;如果是可加载模块,则会被标记为模块的初始化函数,在模块加载时由insmod或modprobe调用。 所以,当模块被编译进内核时,module_init对应的初始化函数会在device_initcall阶段执行,而late_initcall则是在更晚的阶段执行。因此,它们的执行顺序不同,导致用途也不同。late_initcall通常用于那些需要等待其他子系统初始化完成后再执行的代码。 需要确保这些信息准确无误,可能需要引用相关的内核文档或书籍。例如,《Linux设备驱动程序》一书中可能提到这些初始化宏的使用方法。另外,应该给出示例代码,说明如何在实际模块中使用这两个宏,以及它们在内核启动时的执行顺序差异。 用户可能还想知道为什么会有不同的初始化宏,以及如何选择合适的宏。这时候需要解释内核初始化的阶段划分,以及不同子系统之间的依赖关系。例如,某些驱动可能依赖于其他子系统已经初始化完成,因此需要将它们的初始化函数放在较晚的阶段。 最后,总结两者的主要区别:执行顺序不同,使用场景不同。同时,提醒用户注意模块是内置还是可加载的情况,因为module_init的行为会有所不同。如果是可加载模块,其初始化函数在模块插入时执行,而内置模块则在对应的初始化阶段执行。 在生成相关问题时,需要考虑用户可能进一步的问题,例如其他初始化宏的区别,或者如何调试初始化顺序问题。这样可以帮助用户更深入地理解内核模块的初始化机制。</think>### module_initlate_initcall区别用法 #### 一、基本定义 1. **module_init** 是Linux内核模块最常用的初始化宏,用于声明模块的入口函数。根据模块类型(内置/可加载)有不同的行为: - 当模块**编译进内核**时,初始化函数在`device_initcall`阶段执行(第6级) - 当模块**动态加载**时,初始化函数在`insmod/modprobe`时执行 2. **late_initcall** 属于内核初始化阶段中**最后一级**的初始化宏(第7级),专门用于需要延迟执行的初始化操作[^1] #### 二、执行顺序对比 $$ \begin{array}{|c|c|} \hline \text{初始化阶段} & \text{优先级} \\ \hline core\_initcall & 1 \\ postcore\_initcall & 2 \\ arch\_initcall & 3 \\ subsys\_initcall & 4 \\ fs\_initcall & 5 \\ device\_initcall & 6 \\ late\_initcall & 7 \\ \hline \end{array} $$ #### 三、典型使用场景 1. **module_init** 设备驱动初始化(如注册PCI驱动)、子系统注册等需要较早初始化的操作 ```c // 网络驱动示例 static int __init mynet_init(void) { register_netdev(net_device); } module_init(mynet_init); ``` 2. **late_initcall** 需要等待其他子系统就绪的操作,例如: - 依赖文件系统初始化的模块 - 需要最后初始化的硬件组件 - 系统状态监控模块 ```c // 延迟初始化示例 static int __init late_demo(void) { printk("This runs after all regular initcalls"); } late_initcall(late_demo); ``` #### 四、关键差异总结 | 特性 | module_init | late_initcall | |---------------------|--------------------------------|-----------------------| | 执行阶段 | 第6级(内置模块)或动态加载时 | 第7级 | | 模块类型 | 支持动态和静态模块 | 仅静态编译进内核的模块| | 典型延迟 | 10ms级 | 100ms级 | | 依赖关系处理 | 常规依赖 | 强延迟依赖 | #### 五、调试技巧 1. 查看初始化顺序: ```bash dmesg | grep "initcall" ``` 2. 通过`/sys/module/`查看模块初始化状态: ```bash ls /sys/module/<module_name>/initstate ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值