In embedded system development, the Linux kernel is the core of the entire system. Understanding the kernel boot mechanism not only helps developers build a complete system understanding but also plays an important role in troubleshooting boot anomalies, performance optimization, and kernel trimming. This article will systematically analyze the embedded Linux kernel boot process from the perspectives of Bootloader Stage、Kernel Assembly Initialization、C Language Initialization、Device Tree Parsing、User Space Startup.
1. Overview of Linux Kernel Boot
The Linux kernel boot can be understood as the complete link from powering on the CPU to the execution of the first user-mode process. In embedded systems, due to the diversity of hardware platforms, the boot process varies slightly, but the overall logic remains consistent:
-
Bootloader Stage The Bootloader (commonly U-Boot) completes the lowest level hardware initialization, memory checks, kernel and device tree loading, and sets boot parameters.
-
Kernel Stage The CPU jumps to the kernel
<span>_start</span>entry to execute assembly initialization, and then enters the C language environment to complete the initialization of various kernel subsystems. -
User Space Stage The kernel mounts rootfs and starts the first user space process (
<span>init</span>/<span>systemd</span>), and the system enters an available state.
The entire process is illustrated as follows (flowchart available in the public account):
[CPU Power On] -> [Bootloader Initialization] -> [Kernel Assembly Stage] -> [start_kernel()] -> [Subsystem Initialization] -> [Mount rootfs] -> [Start init process]
2. Detailed Explanation of Bootloader Stage
The Bootloader is the first step in system startup; it is responsible not only for loading the kernel image but also for hardware initialization and setting boot parameters. Taking U-Boot as an example:
1. CPU and Memory Initialization
-
After powering on, the CPU is in a specific mode (ARM: SVC/Monitor), and the Bootloader switches to executable kernel mode.
-
Initializes the SDRAM/DDR controller to ensure memory is available.
-
Sets the early stack for early exception handling.
2. Loading Kernel Image and DTB
-
The Bootloader copies the zImage/uImage kernel to a specified location in physical memory.
-
Loads the device tree file (DTB) into memory for the kernel to parse hardware information.
-
The kernel startup address is set by the Bootloader, which then jumps to execute
<span>_start</span>
3. Passing Kernel Startup Parameters
Startup parameters are passed via <span>bootargs</span>:
console=ttyS0,115200 root=/dev/mmcblk0p2 rw earlyprintk
-
<span>console</span>: Specifies the serial console. -
<span>root</span>: The device to mount the root filesystem. -
<span>earlyprintk</span>: Early print debugging information. -
These parameters are parsed early in the kernel startup, affecting driver initialization, debugging output, and kernel behavior.
4. Jumping to Kernel Entry
-
The Bootloader sets the CPU to kernel mode.
-
Jumps to the
<span>_start</span>assembly entry, and the kernel officially begins its initialization.
The Bootloader stage is the foundation of embedded system startup; optimizing Bootloader initialization time can significantly reduce system boot time.
3. Kernel Assembly Stage <span>_start</span>
After the kernel image is loaded, the CPU executes the <span>_start</span> assembly code (located in <span>arch/arm/kernel/head.S</span> or the corresponding architecture path), which is the first step of kernel startup.
1. CPU Mode and Stack Setup
-
The ARM CPU switches to kernel mode.
-
Allocates early stack for each CPU core.
-
Sets the exception vector table to ensure correct exception handling.
2. Data Segment and Page Table Initialization
-
Clears the BSS segment.
-
Initializes kernel global data structures.
-
Establishes early page tables and enables the MMU (Memory Management Unit).
3. Calling C Language Entry <span>start_kernel()</span>
-
<span>_start</span>assembly completes, and calls<span>start_kernel()</span> -
The kernel enters the C language environment and begins complete system initialization.
Although the assembly stage is brief, each step is a cornerstone of the startup; incorrect stack or page table configurations can prevent the system from booting.
4. <span>start_kernel()</span>: Core of Kernel Initialization
<span>start_kernel()</span> is located in <span>init/main.c</span>, and is the central function of kernel startup, mainly completing the following tasks:
1. Kernel Print and Debug Initialization
-
Disables interrupts to ensure early initialization safety.
-
Initializes the
<span>printk</span>mechanism for outputting logs.
printk(KERN_INFO "Linux version %s\n", init_utsname()->release);
2. Architecture-Related Initialization <span>setup_arch()</span>
-
Initializes memory mapping and page tables.
-
Confirms the number of CPU cores and topology.
-
Scans the Device Tree to identify platform hardware.
3. Subsystem Initialization
-
Memory Management: buddy system, SLAB/SLUB allocators.
-
Timers and Soft Interrupts: Initializes tick, jiffies.
-
Scheduler: Sets idle thread, scheduling policy.
4. Creating Init Thread and Idle Thread
-
Idle thread: The idle thread for each CPU core.
-
Init thread: The first user-mode startup thread.
-
Calls
<span>rest_init()</span>to create kernel threads and prepare the environment for user space to run.
5. System Dependency Initialization
-
Preparation for mounting the filesystem.
-
Preparation for driver probe stage.
-
Network subsystem initialization.
<span>start_kernel()</span>is the brain of kernel startup; all system functions depend on it for early configuration.
5. Device Tree Parsing
The Device Tree is the core mechanism for hardware abstraction in embedded Linux systems.
1. Role of Device Tree
-
Describes hardware structure (CPU, memory, peripherals).
-
Platform-independent, allowing the kernel to boot across platforms.
-
Provides driver matching information.
2. Kernel Parsing Process
-
The Bootloader loads the DTB file into memory.
-
The kernel early calls
<span>early_init_dt_scan()</span>to parse the DT. -
Builds the platform device list.
-
Drivers match DT nodes through
<span>of_match_table</span>and execute<span>probe()</span>
3. DT Example
uart1: serial@40011000 { compatible = "vendor,my-uart"; reg = <0x40011000 0x1000>; interrupts = <5>; clocks = <&uart_clk>; };
Drivers match with the <span>compatible</span> field and <span>of_match_table</span> to achieve automatic binding.
6. Kernel Parameter Parsing
The parameters passed by the Bootloader are parsed early in the kernel startup, mainly affecting:
-
Console output (console).
-
Root filesystem mounting (root).
-
Startup process (init).
-
Debug output (earlyprintk).
char *cmdline = saved_command_line; parse_early_param(cmdline);
Proper parameter configuration can accelerate startup, facilitate debugging, and trim the kernel.
7. User Space Startup
After kernel initialization is complete:
-
Mounts rootfs (memory or storage device).
-
Starts the first user-mode process
<span>init</span>/<span>systemd</span> -
The CPU enters scheduler control, and the multitasking system begins to run.
-
The system officially enters an available state.
User space startup marks the completion of kernel startup, concluding the entire process from powering on the embedded device to system availability.
8. Startup Optimization and Practical Tips
After understanding the startup process, the following optimization strategies can be adopted in actual projects:
-
Accelerating Startup
-
Simplifying Bootloader initialization.
-
Trimming unnecessary modules from the kernel.
-
Delaying initialization of non-critical drivers.
Debugging Techniques
-
Using early printk for serial output.
-
Analyzing hang points in the startup process.
-
Checking
<span>/proc/cmdline</span>and<span>/proc/bootconfig</span>
Performance Optimization
-
Optimizing CPU initialization order.
-
Delaying driver probe.
-
Optimizing rootfs mounting.
System Reliability
-
Analyzing startup dependency order.
-
Avoiding driver loading conflicts.
9. Conclusion
The Linux kernel startup is a precise and complex process, from Bootloader to assembly initialization, then to C language initialization, device tree parsing, and user space startup. Each step carries the foundation of system stability and performance. Mastering the startup process helps with:
-
Locating startup anomalies.
-
Trimming the kernel and accelerating startup.
-
Driver development and debugging.
-
Building a complete cognitive framework for embedded systems.
#Embedded Panorama Series #Linux Kernel Architecture #Performance Optimization Practice
Next Article Preview
After understanding the kernel boot mechanism, the next step is to master the Driver Model and Device Tree. The next article “Panorama of Embedded Systems: Interpretation of Driver Model and Device Tree” will analyze the driver lifecycle, platform driver mechanism, character/block device and device tree binding principles from the ground up, helping you build a complete understanding of hardware abstraction and driver development.