程序加载的“调度员”:从存储介质到内存的搬运工
完成硬件初始化后,
Bootloader的核心任务转向“程序加载”——将存储在非易失性介质(如Flash、硬盘)中的操作系统内核或应用程序,搬运到内存(RAM)中并启动。这一过程如同将演出道具从仓库搬运到舞台,需要精准的地址定位、数据校验和跳转执行。
程序加载的第一步是“定位目标程序”。在嵌入式系统中,操作系统内核通常存储在特定的Flash分区中,例如在Linux系统中,内核镜像可能存放在“kernel”分区的0x08020000地址。Bootloader会通过解析分区表(如MBR、GPT或自定义分区表),找到目标程序的起始地址和大小,并检查分区的完整性——若分区表损坏或程序大小超过分区容量,Bootloader会进入错误处理流程(如通过LED闪烁报警)。
数据搬运过程需要兼顾速度与可靠性。对于NOR Flash等支持随机读取的存储介质,Bootloader可直接通过地址映射读取数据;而对于NAND Flash,由于其按页读取的特性,Bootloader需要先发送页地址命令,再读取整页数据并搬运到内存。为防止数据传输错误,Bootloader会对每块搬运的数据进行校验:简单场景下使用校验和(Checksum),复杂场景则采用CRC32算法,若校验失败则重新读取,直至成功或达到重试上限。
程序加载的最后一步是“地址重定位”。许多程序在编译时采用“位置无关代码”(PIC),可在任意内存地址运行,但部分内核程序需要固定在特定地址执行。
Bootloader会根据程序的链接脚本信息,将代码段、数据段、BSS段搬运到内存的指定位置:代码段(Text)存放可执行指令,通常加载到低地址区域;数据段(Data)存放初始化的全局变量,加载到读写区域;BSS段存放未初始化的全局变量,加载后会被清零。这一步确保了程序能按照编译时的预期地址运行,避免因地址错乱导致的崩溃。