linux - 编译到内核中的驱动程序的 init 函数调用

标签 linux operating-system linux-kernel linux-device-driver

在 Linux 中,如果设备驱动程序被构建为可加载的内核模块,那么在插入设备驱动程序内核模块时,内核会调用 module_init() 宏所指出的设备驱动程序的 init 函数。

这对于静态编译到内核中的设备驱动程序是如何工作的?他们的 init 函数是如何调用的?

最佳答案

内置驱动程序的 init 例程仍然可以使用 module_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.
 */

我假设设备驱动程序的这些子部分对应于Linux内核源代码树的drivers目录中的子目录,并且链接顺序记录在< drivers 中每个子目录的 em>built-in.o 文件。因此在内核引导期间,每个内置驱动程序的 init 例程最终由 do_initcalls() 中的 init/main.c 执行。

设备驱动程序的 init 例程负责探测系统以验证 HW 设备是否确实存在。当探测失败时,驱动程序不应分配任何资源或注册任何设备。

更新:
在内核命令行上传递选项“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

引用:http://elinux.org/Initcall_Debug

关于linux - 编译到内核中的驱动程序的 init 函数调用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12865054/

相关文章:

ruby - 当 shell 有子进程时,为什么 ruby​​ 的 PTY 库无法捕获输入?

c - 操作系统开发捷径

c# - 我如何测量在进程上下文切换中花费的时间的近似值?

c - 等待子进程而不释放其资源

linux - 如何在 Linux 中限制 Matlab 的 CPU 使用率

java - 错误 : Could not find or load main class

php - 如何从非拥有文件夹中的 apache 用户运行脚本?

c# - 如何拦截操作系统函数调用

debugging - 如何调试内核死锁问题

linux-kernel - 如何定义内核模块之间的依赖关系?