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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/11642330/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-06 13:54:12  来源:igfitidea点击:

What is the Linux built-in driver load order?

linuxlinux-kernellinux-device-driver

提问by Dien Nguyen

How can we customize the built-in driver load order (to make some built-in driver module load first, and the dependent module load later)?

如何自定义内置驱动加载顺序(先加载一些内置驱动模块,再加载依赖模块)?

采纳答案by Yasushi Shoji

Built-in drivers wont be loaded, hence built-in. Their initialization functions are called and the drivers are activated when kernel sets up itself. These init functions are called in init/main.c::do_initcalls(). All init calls are classified in levels, which are defined in initcall_levelsand include/linux/init.h

内置驱动程序不会被加载,因此是内置的。当内核自行设置时,它们的初始化函数被调用并且驱动程序被激活。这些 init 函数在init/main.c::do_initcalls(). 所有 init 调用都按级别分类,这些级别定义在initcall_levelsinclude/linux/init.h

These levels are actuall symbols defined in linker script (arch/*/kernel/vmlinux.lds.*). At kernel compile time, the linker collects all function marked module_init()or other *_initcall(), classify in levels, put all functions in the same level together in the same place, and create like an array of function pointers.

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

What do_initcall_level() does in the run-time is to call each function pointed by the pointers in the array. There is no calling policy, except levels, in do_initcall_level, but the order in the array is decided in the link time.

do_initcall_level() 在运行时所做的就是调用数组中指针指向的每个函数。do_initcall_level 中除了levels 没有调用策略,但是数组中的顺序是在link time 中决定的。

So, now you can see that the driver's initiation order is fixed at the link time, but what can you do?

那么,现在你可以看到驱动程序的启动命令在链接时是固定的,但是你能做什么呢?

  1. put your init function in the higher level, or
  2. put your device driver at the higher position in Makefile
  1. 将您的 init 函数置于更高级别,或
  2. 将您的设备驱动程序放在更高的位置 Makefile

The first one is clear if you've read the above. ie) use early_initcall() instead if it is appropriate.

如果您已阅读以上内容,第一个就很清楚了。即)如果合适,请改用 early_initcall()。

The second one needs a bit more explanation. The reason why the order in a Makefilematter is how the current kernel build system works and how the linkers works. To make a long story short, the build system takes all object files in obj-yand link them together. It is highly environment dependent but there is high probability that the linker place first object file in the obj-yin lower address, thus, called earlier.

第二个需要多一点解释。Makefile事情中的顺序的原因是当前内核构建系统的工作方式以及链接器的工作方式。长话短说,构建系统接收所有目标文件obj-y并将它们链接在一起。它高度依赖于环境,但链接器很可能将第一个目标文件放在obj-yin 较低地址中,因此会更早调用。

If you just want your driver to be called earlier than other drivers in the same directory, this is simplest way to do it.

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

回答by Basile Starynkevitch

Correct module order and dependencies are handled by modprobe, even within the initrd.

正确的模块顺序和依赖关系由modprobe处理,即使在initrd 中

回答by Ignacio Vazquez-Abrams

depmodexamines the symbols exported and required by each module and does a topological sort on them that modprobecan later use to load modules in the proper order. Requiring the symbols from modules you wish to be dependent on is enough for it to do the right thing.

depmod检查每个模块导出和需要的符号,并对它们进行拓扑排序,以便modprobe以后以正确的顺序加载模块。从你希望依赖的模块中获取符号就足以让它做正确的事情。

回答by Nagi

Recently i got this problem my charger driver is having dependency on ADC driver so before loading ADC driver charger driver has loaded and checking for adc phandle which is defined in DTS file and has to intialize by ADC driver. its got resolved by changing the order of the module in drivers/Makefile

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