从零写OS(四十):per-CPU 调度器 —— 每核一个时钟

ch39 加了锁,数据安全了。但调度器还有个问题:PIT(8253 定时器)是系统里唯一的一个,只有 CPU0 能收到 IRQ0。AP 没有定时中断,没法触发调度。 这章做两件事: 用 LAPIC 定时器替代 PIT,每颗核心独立触发调度 把 current_proc 改成 per-CPU 变量,每颗核各自记录自己在跑哪个进程 全局 current_proc 的灾难 int current_proc = 0; // 全局变量 // CPU0 把它改成 3(选中进程3) // CPU1 同时把它改成 5 // CPU0 接着继续,以为自己在跑进程3,实际内存里已经是 5 // → 崩溃 解决方法是每颗核心维护自己的 current_proc,互不干扰: typedef struct { int cpu_id; int current_proc; } cpu_t; cpu_t cpus[MAX_CPUS]; static inline cpu_t *this_cpu(void) { // 读 LAPIC ID → 查表 → 返回本核的 cpu_t int lid = lapic_id(); for (int i = 0; i < ncpus; i++) if (cpu_lapic_ids[i] == lid) return &cpus[i]; return &cpus[0]; } #define CUR_PROC (this_cpu()->current_proc) 所有原来用 current_proc 的地方改成 CUR_PROC。CPU0 修改自己的,CPU1 修改自己的,互不干扰。 ...

June 4, 2026 · 2 min · 大飞

从零写OS(三十八):SMP 启动 —— 唤醒第二颗 CPU

到目前为止,内核一直跑在单核上。这一章迈出多核的第一步:让所有 CPU 核心都进入内核。 验证结果: [acpi] MADT found, 2 CPU(s) [smp] booting AP lapic=1 [cpu0] online [cpu1] online [smp] all APs online, total CPUs=2 / # x86 多核启动的规则 x86 多核启动有一套固定规则。系统上电后只有一颗 CPU 跑起来,叫做 BSP(Bootstrap Processor)。其余的核心叫 AP(Application Processor),处于等待状态,需要 BSP 主动唤醒。 唤醒的方式是通过 LAPIC(Local APIC) 发送 IPI(Inter-Processor Interrupt)。每颗核心内置一个 LAPIC,是核间通信的硬件基础。 第一步:找到所有 CPU CPU 的信息藏在 ACPI MADT 表里。MADT(Multiple APIC Description Table)是固件写好放在内存里的一张表,描述了系统上有多少颗 CPU 以及每颗 CPU 的 LAPIC ID。 内核启动时扫描 MADT,把所有有效 CPU 的 LAPIC ID 记下来: void acpi_parse_madt(void) { madt_t *madt = acpi_find_table("APIC"); // 遍历所有条目,找 type=0 的 Processor Local APIC 条目 // 记录 lapic_id → cpu_lapic_ids[],ncpus++ } 第二步:发送 INIT + STARTUP IPI 唤醒 AP 的序列是固定的(来自 Intel SDM): ...

June 4, 2026 · 2 min · 大飞
京ICP备14031575号-3