在Linux中,如果设备驱动程序被构建为可加载的内核模块,然后在插入的设备驱动程序内核模块,内核由module_init()
宏调用设备驱动程序的初始化函数如指出。函数调用编译到内核
这是如何工作的设备驱动程序静态编译进内核?他们的init函数是如何调用的?
在Linux中,如果设备驱动程序被构建为可加载的内核模块,然后在插入的设备驱动程序内核模块,内核由module_init()
宏调用设备驱动程序的初始化函数如指出。函数调用编译到内核
这是如何工作的设备驱动程序静态编译进内核?他们的init函数是如何调用的?
init例程的内置驱动程序仍然可以使用宏来声明该入口点。或者驱动程序永远不会被编译为可加载模块时,驱动程序可以使用device_initcall()
。或者在引导序列的早期阶段移动它的初始化,驱动程序可以使用subsys_initcall()
。
在include/linux/init.h
用于调用这些INIT例程的顺序被描述为:
/* 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.
*/
我假定这些小节设备驱动程序对应于子目录drivers
目录Linux内核源树的内,那链接顺序被记录在drivers
的内置in.o文件中的每个子目录。所以内核引导的初始化例行每个内置驱动程序的过程中,通过do_initcalls()
在init/main.c
最终执行。
init设备驱动程序的例程负责探测系统以验证硬件设备是否真实存在。探针失败时,驱动程序不应分配任何资源或注册任何设备。
UPDATE:
跑过内核命令行选项“initcall_debug”将导致定时信息被输出到控制台每个initcall。 initcalls用于初始化静态链接的内核驱动程序和子系统,并为Linux启动过程贡献大量时间。输出看起来像:
calling tty_class_init+0x0/0x44 @ 1
initcall tty_class_init+0x0/0x44 returned 0 after 9765 usecs
calling spi_init+0x0/0x90 @ 1
initcall spi_init+0x0/0x90 returned 0 after 9765 usecs
按规定在内核中的评论init.h里
“宏module_init()要么do_initcalls()时被调用(如果内置)或在模块 插入时间(如果一个模块)。“
如果你看看初始化。h然后你会看到
define module_init(x)__initcall(x);
而且如果你仔细观察,然后
定义__initcall(FN)device_initcall(FN)
而且
定义device_initcall(FN)__define_initcall( “6” ,fn,6)
因此,基本上,模块init会在引导时导致initcall(注意:仅适用于静态编译模块)。
假设我想为驱动程序使用device_initcall,我有一个问题。在需要调用此驱动程序的boardfile的哪一部分中。 – kzs
通过*“boardfile”*,我假设您指的是arch或mach或板初始化代码,通常在引导过程中很早就被称为。 'init/main.c'中的'do_initcalls()'通常在大多数HW初始化之后发生。内核代码很少被构造成调用驱动程序,除非它是'ops'函数或其他模块接口入口点。你真的问过什么样的“电话”? – sawdust
是的,你得到了电路板文件。并且do_initcalls何时被调用非常明确。 “你真的问过什么样的”呼叫“?为此,我想这样说:假设我有3种switch_dev类型的设备(它们的状态需要导出到用户空间)。在这里,设备调用device_initcall(随例程提供,使对象switch_dev-> kobj可用于其他2个设备)。其他两个设备使用正常的module_init。我的兴趣是将device_initcall例程移动到board文件并为所有模块使用module_init 3.如何做到这一点? – kzs