Invocación de función init de controladores comstackdos en kernel

En Linux, si los controladores de dispositivo se construyen como módulos de núcleo cargables, al insertar el módulo de kernel del controlador de dispositivo, el núcleo llama a la función init del controlador de dispositivo como lo señala la macro module_init() .

¿Cómo funciona esto para los controladores de dispositivo que están comstackdos estáticamente en el kernel? ¿Cómo se llama su función init?

La rutina de inicio de un controlador integrado aún puede usar la macro module_init() para declarar ese punto de entrada. O el controlador puede usar device_initcall() cuando el controlador nunca se comstackrá como un módulo cargable. O para mover su inicialización muy temprano en la secuencia de inicio, el controlador podría usar subsys_initcall() .

En include/linux/init.h la secuencia para invocar estas rutinas de inicio se describe como:

 /* 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. */ 

Supongo que estas subsecciones para controladores de dispositivos corresponden a los subdirectorios dentro del directorio de controladores del árbol fuente del kernel de Linux, y que el orden de los enlaces se registra en el archivo built-in.o de cada subdirectorio en los drivers . Por lo tanto, durante el arranque del kernel, la rutina de inicio de cada controlador incorporado se ejecuta finalmente mediante do_initcalls() en init/main.c

La rutina de inicio del controlador del dispositivo es responsable de probar el sistema para verificar que el dispositivo HW realmente exista. El controlador no debe asignar ningún recurso ni registrar ningún dispositivo cuando falla la sonda.

ACTUALIZAR :
Al pasar la opción “initcall_debug” en la línea de comandos del kernel, se imprimirá información de temporización en la consola para cada llamada de inicio. Las llamadas initcalls se usan para inicializar los controladores y subsistemas del kernel enlazados estáticamente y contribuyen con una cantidad significativa de tiempo al proceso de arranque de Linux. La salida se ve así:

 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 

Referencia: http://elinux.org/Initcall_Debug

Según lo especificado por los comentarios en kernel init.h

“module_init () se llamará durante do_initcalls () (si está incorporado) o en el momento de inserción del módulo (si es un módulo)”.

Si miras en init.h entonces verás

define module_init (x) __initcall (x);

Y si observas de cerca entonces

define __initcall (fn) device_initcall (fn)

Y

define device_initcall (fn) __define_initcall (“6”, fn, 6)

Así que, básicamente, el módulo init conduce a initcall ( NOTA: solo para módulos comstackdos estáticamente ) en el momento del arranque solamente.