Linux内置驱动程序的加载顺序是什么?

Linux内置驱动程序的加载顺序是什么?,linux,linux-kernel,linux-device-driver,Linux,Linux Kernel,Linux Device Driver,我们如何定制内置驱动程序加载顺序(先加载一些内置驱动程序模块,然后加载相关模块)?正确的模块顺序和相关性由,即使在.depmod中,也会检查每个模块导出和所需的符号,并对其进行拓扑排序,modprobe可用于以后按正确顺序加载模块。需要您希望依赖的模块中的符号就足以让它做正确的事情。内置驱动程序无法加载,因此内置驱动程序。当内核自行设置时,会调用它们的初始化函数并激活驱动程序。这些init函数在init/main.c::do_initcalls()中调用。所有init调用都按级别分类,这些级别在

我们如何定制内置驱动程序加载顺序(先加载一些内置驱动程序模块,然后加载相关模块)?

正确的模块顺序和相关性由,即使在.

depmod
中,也会检查每个模块导出和所需的符号,并对其进行拓扑排序,
modprobe
可用于以后按正确顺序加载模块。需要您希望依赖的模块中的符号就足以让它做正确的事情。

内置驱动程序无法加载,因此内置驱动程序。当内核自行设置时,会调用它们的初始化函数并激活驱动程序。这些init函数在
init/main.c::do_initcalls()
中调用。所有init调用都按级别分类,这些级别在
initcall\u levels
include/linux/init.h

这些级别实际上是链接器脚本(
arch/*/kernel/vmlinux.lds.*
)中定义的所有符号。在内核编译时,链接器收集所有标记为
module_init()
或其他
*\u initcall()
的函数,按级别分类,将同一级别的所有函数放在同一位置,并创建一个函数指针数组

_initcall_level()在运行时的作用是调用数组中指针指向的每个函数。在do_initcall_级别中,除了级别之外,没有调用策略,但是数组中的顺序在链接时间中决定

那么,现在您可以看到,驱动程序的启动顺序在链接时间是固定的,但是您能做什么呢

  • 将init函数置于更高级别,或者
  • 将设备驱动程序放在
    Makefile
  • 如果你读过上面的内容,第一点就很清楚了。ie)如果合适,请使用early_initcall()

    第二个需要更多的解释。
    Makefile
    中的顺序之所以重要,是因为当前的内核构建系统如何工作以及链接器如何工作。长话短说,构建系统获取
    obj-y
    中的所有对象文件并将它们链接在一起。它高度依赖于环境,但链接器很有可能将第一个对象文件放在
    obj-y
    的较低地址中,因此称为较早的地址


    如果您只想让您的驱动程序比同一目录中的其他驱动程序更早被调用,这是最简单的方法。

    最近我遇到了这个问题,我的充电器驱动程序依赖于ADC驱动程序,因此在加载ADC驱动程序之前,充电器驱动程序已加载并检查DTS文件中定义的ADC幻影,必须由ADC驱动程序初始化。通过更改drivers/Makefile中模块的顺序,问题得以解决

    感谢@Yasushi Shoji的详细解释!