xv6 rev-11中mycpu()为何能为每个CPU返回不同结构体?
为什么xv6的mycpu()能为不同CPU返回对应的struct cpu结构体
核心原因在于本地APIC(Local APIC)的内存映射IO(MMIO)特性:
虽然lapic是全局共享的指针,但它指向的是一个MMIO地址(通常是0xFEE00000)。当不同CPU访问这个地址时,x86硬件会自动将访问路由到当前执行CPU的本地APIC寄存器,而不是同一个物理寄存器。
具体代码分析
- lapicid()函数:
volatile uint *lapic; // Initialized in mp.c lapicid(void) { if (!lapic) return 0; return lapic[ID] >> 24; }
当CPU调用lapic[ID]时,实际是读取当前CPU自身本地APIC的ID寄存器,所以每个CPU得到的都是自己独有的APIC ID,而非同一个值。
- mycpu()函数:
mycpu(void) { int apicid, i; if(readeflags()&FL_IF) panic("mycpu called with interrupts enabled"); apicid = lapicid(); // APIC IDs are not guaranteed to be contiguous. Maybe we should have // a reverse map, or reserve a register to store &cpus[i]. for (i = 0; i < ncpu; ++i) { if (cpus[i].apicid == apicid) return &cpus[i]; } }
每个CPU拿到自己的APIC ID后,遍历全局的cpus数组,找到与自身APIC ID匹配的struct cpu实例并返回,自然就实现了不同CPU获取对应结构体的效果。
补充:代码注释也提到APIC ID不一定连续,所以用遍历方式查找;如果要优化,可以建立APIC ID到struct cpu的反向映射,或者专门用一个寄存器存储当前CPU的struct cpu指针,避免每次遍历。
内容的提问来源于stack exchange,提问作者Jacky Wang
相关产品推荐
相关产品推荐

