Ban*_*oot 4 linux operating-system linux-device-driver linux-kernel
在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.
*/
Run Code Online (Sandbox Code Playgroud)
我假设设备驱动程序的这些子部分对应于driversLinux内核源代码树目录中的子目录,并且链接顺序记录在每个子目录的内置.o文件中drivers.因此在内核启动期间,每个内置驱动程序的init例程最终都由do_initcalls()in 执行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
Run Code Online (Sandbox Code Playgroud)
参考:http://elinux.org/Initcall_Debug