Skip to content

导引:点亮什么、为什么、设计图

这一章我们要点亮什么

两件看得见的事。

第一件,kprintf 终于像个 printf 了。011 的 kprintf 其实已经能 %d/%u/%x/%X/%p,也有 %Nd/%0Nd 的宽度与零补;这一章真正补的是左对齐(%-)、把负数零补的坑修对(-00042 而不是 000-42),并顺手把引擎抽成 header-only 模板让它能在 host 上单测。于是你能写出 kprintf("%-8x", 0xdead) 这种带对齐的诊断输出,而不必自己手拼字符串。

第二件,稍微惊悚一点:-O2(Release)构建的内核,以前根本起不来。它在加载 IDT 的当口安静地 Triple Fault,QEMU 直接退出,连一句遗言都不留。这一章把它修了,从那以后无论 Debug 还是 Release,内核都能稳稳跑到 idle loop。

为什么现在需要它

先说为什么是现在。011 之后内核已经能响应时钟中断,接下来 013 就要往屏幕上画字、动 framebuffer,用户态、文件系统也在不远处。可一旦系统复杂起来,调试就全压在 kprintf 一根线上——它就是我们的眼睛。这时候如果 kprintf 连个对齐都打不好、连个指针都格式化不利索,后面每一处排查都会被它拖累。所以在往系统里堆新东西之前,先花一章把 kprintf 做扎实,是一笔稳赚的投资。

重构的过程中,一个潜伏的 bug 被顺带逼了出来。我们想把 kprintf 的格式化引擎抽出来做单元测试,测试要在 host 上用 -O2 编译(因为那才是发布内核会跑的优化级别)。结果一编——内核在 idt_init 里 Triple Fault 了。这不是 kprintf 的锅,但它像一面镜子,照出了一个从 010 起就一直藏在那儿、只是之前没被 -O2 照到的硬件初始化缺陷:引导期从没初始化 SSE。

这就是这一章为什么是「两个地基」:一个是软件地基(kprintf),一个是硬件地基(SSE),它俩凑在一个 tag 里,因为正是在给 kprintf 做 -O2 单测的时候,后者才暴露。

设计图

kprintf 重构后的形状,核心是「格式化引擎」和「输出后端」彻底分家,中间靠一个回调连起来:

text
  ┌─────────────────────────────────────┐
  │  vkprintf_impl<OutputFn>(out,fmt,va) │  ← 硬件无关,header-only 模板
  │  纯逻辑:解析 % 宽度 对齐,格式化数字  │     kernel/lib/private/vkprintf_impl.hpp
  └───────────────┬─────────────────────┘
                  │ 每产出一个字符 → out(c)

  ┌─────────────────────────────────────┐
  │  回调 lambda                          │
  │  [&](char c){ g_serial.putc(c); }     │  ← big kernel:喂给串口
  └───────────────┬─────────────────────┘

  ┌─────────────────────────────────────┐
  │  输出后端                             │
  │  big kernel: Serial(COM1)            │     host 单测: std::string
  │  (013 之后还会多一路: framebuffer)   │
  └─────────────────────────────────────┘

同一个引擎,big kernel 喂给串口,host 单测喂给一个 std::string。013 之后还会多一路屏幕——到那时你就明白这层回调当初为什么要抽出来了。

SSE 那条线是另一回事,它埋在 boot 流程最开头:

text
  mini kernel boot.S _start
     │  cli
     │  ★ 设 CR4.OSFXSR(bit9) + CR4.OSXMMEXCPT(bit10) + clts   ← 本章新增
     │  ... 进入长模式、加载 big kernel ...

  big kernel main: kprintf_init → GDT → IDT(idt_init 内部清零,可能被 -O2 向量化为 SSE)

关键在于这个 ★ 出现在内核最早的可执行指令处。它的意义下面讲 SSE 那节展开。

035_multi_terminal-45-gf25de18 · f25de18 · 2026-08-04