2. 计算机启动过程简介:从加电到操作系统加载
说实话,很多做CPU优化的同学,一上来就盯着操作系统里的调度器、缓存命中率。但我跟你讲,如果你不了解机器刚从加电到OS接管这段时间发生了什么,后面很多优化你可能都找不到根儿。我自己刚入行时也是忽略了这个过程,结果一次调启动时间,死活降不下来——后来才发现,问题出在固件里的MTRR配置上。好,咱们走一遍。
2.1 加电与复位
电源一接通,主板上所有器件收到一个确定的电压。CPU的复位引脚被拉高,内部逻辑立刻进入复位状态。说白了,CPU此时还不知道自己要干什么——复位向量决定了一切。x86架构下,CPU从复位向量 0xFFFFFFF0 开始取指令,那里通常是一个跳转指令,指向BIOS/UEFI的入口。
2.2 固件初始化(BIOS/UEFI)
固件程序开始运行后,第一件事是POST(开机自检)。它会扫描内存、检测关键设备。你可能会想,这跟CPU优化有什么关系?其实关系大了。POST阶段会初始化CPU微码、设置MTRR、配置MSR寄存器。这些设置直接影响后续OS启动时的缓存行为。
- 微码加载:BIOS会从ROM读取最新的微码更新并加载到CPU内部。没这一步,一些CPU bug可能导致随机宕机。
- MTRR配置:定义哪些内存区域是强缓存、哪些是弱缓存。我在项目中遇到过,BIOS忘记把显存区域设为UC(不可缓存),导致图形驱动性能暴跌。
- APIC初始化:多核系统会初始化本地APIC和I/O APIC,为后续中断管理打基础。
一个关键点:从实模式到保护模式的切换发生在固件后期或引导加载程序阶段。CPU通过修改CR0控制寄存器进入保护模式,开启分段和分页。这个切换成本不低,但一旦完成,32位或64位寻址能力就打开了。
2.3 引导加载程序(Bootloader)
固件扫描启动设备,找到有效的主引导记录(MBR)或分区,然后把控制权交给引导加载程序。常见的如GRUB、UEFI Shell。
引导加载程序做什么?我简单归纳一下:
- 加载内核映像(vmlinuz、bzImage)到内存。
- 设置实模式与保护模式之间的切换代码(比如`go_to_protected_mode`)。
- 准备启动参数(cmdline),比如`acpi=off`、`nohz=full`这些CPU调优参数就是在这儿传递的。
- 解析内核头部的魔数和配置。
- 跳转到内核入口(32位或64位保护模式入口)。
2.4 内核加载与初始化
内核入口点通常是start_kernel。这时候CPU已经运行在保护模式或长模式(64位)下。内核会执行以下核心初始化(与CPU强相关):
| 阶段 | 主要工作 | CPU关注点 |
|---|---|---|
| 早期页表建立 | 创建恒等映射和内核映射 | TLB刷新的次数直接拖慢启动 |
| CPU检测 | 识别特性标志(CPUID),开启高端特性 | 你写的优化代码必须依赖这些标志 |
| 中断初始化 | 设置IDT、安装异常处理 | 错误处理中断向量表会浪费CPU周期 |
| SMP启动 | 唤醒其他核心,分发BSP/AP角色 | AP启动时序不当可能造成核心拉扯 |
| 调度器初始化 | 设置任务队列、时钟源 | 时钟中断频率影响上下文切换开销 |
这里我分享一个经历:有一次为了压榨启动速度,我把内核的early_ioremap映射改小了,结果触发了页错误,因为TLB miss后查页表多花了好几个微秒。所以说,CPU优化不能光看代码,要理解它背后的初始化路径。
2.5 手绘图:启动流程总览
下面这张图把整个流程梳了一遍。你一眼就能看到CPU在不同阶段处于什么模式、固件做了什么、内核接过控制后又在忙什么。我画图的时候特意加了模式切换和关键配置两个维度,方便你对应到代码调试。
2.6 本章小结
启动过程其实就是CPU从“裸机”到“受OS管理”的蜕变。我建议你把这张图存下来,调试的时候在脑子里过一遍——现在卡在哪一层?是固件里MTRR没设好,还是内核页表太大?这些问题的根,往往都能从启动流程里找到。
一个小习惯:调启动时间时,我总会在BIOS里打开POST Code日志,然后在内核命令行加上debug initcall_debug。这样你就能看到每个阶段的精确耗时,定位CPU瓶颈就靠它了。