Книга: Embedded Linux Primer: A Practical, Real-World Approach
5.5.1. Initialization via initcalls
5.5.1. Initialization via initcalls
When init() is spawned, it eventually calls do_initcalls(), which is the function responsible for calling all the initialization functions registered with the *_initcall family of macros. The code is reproduced in Listing 5-10 in simplified form.
Listing 5-10. Initialization via initcalls
static void __init do_initcalls(void) {
initcall_t *call;
for (call = &__initcall_start; call < &__initcall_end; call++) {
if (initcall_debug) {
printk(KERN_DEBUG "Calling initcall 0x%p", *call);
print_symbol(":%s()", (unsigned long) *call);
printk("n");
}
(*call)();
}
}
This code is self-explanatory, except for the two labels marking the loop boundaries: __initcall_start and __initcall_end. These labels are not found in any C source or header file. They are defined in the linker script file used during the link stage of vmlinux. These labels mark the beginning and end of the list of initialization functions populated using the *_initcall family of macros. You can see each of the labels by looking at the System.map file in the top-level kernel directory. They all begin with the string __initcall, as described in Listing 5-8.
In case you were wondering about the debug print statements in do_initcalls(), you can watch these calls being executed during bootup by setting the kernel command line parameter initcall_debug. This command line parameter enables the printing of the debug information shown in Listing 5-10. Simply start your kernel with the kernel command line parameter initcall_debug to enable this diagnostic output.[44]
Here is an example of what you will see when you enable these debug statements:
...
Calling initcall 0xc00168f4: tty_class_init+0x0/0x3c()
Calling initcall 0xc000c32c: customize_machine+0x0/0x2c()
Calling initcall 0xc000c4f0: topology_init+0x0/0x24()
Calling initcall 0xc000e8f4: coyote_pci_init+0x0/0x20()
PCI: IXP4xx is host
PCI: IXP4xx Using direct access for memory space
...
Notice the call to customize_machine(), the example of Listing 5-7. The debug output includes the virtual kernel address of the function (0xc000c32c, in this case) and the size of the function (0x2c here.) This is a useful way to see the details of kernel initialization, especially the order in which various subsystems and modules get called. Even on a modestly configured embedded system, dozens of these initialization functions are invoked in this manner. In this example taken from an ARM XScale embedded target, there are 92 such calls to various kernel-initialization routines.
- Initialization and association
- 3.4.2 RTOS Initialization
- Understanding init Scripts and the Final Stage of Initialization
- Chapter 5. Kernel Initialization
- Chapter 6. System Initialization
- 5.2. Initialization Flow of Control
- 5.4. Subsystem Initialization
- 7.4.3. EP405 Processor Initialization
- 7.4.4. Board-Specific Initialization
- 10.3.5. Board-Specific Initialization
- 11.3.2. Example rcS Initialization Script
- 15.5.1. Debugging via Serial Port