x86_64架构与x86架构的内存映射是否一致?
x86 vs x86_64 Memory Mapping: Key Differences & Specifications
嘿,既然你已经写过32位x86的小型内核,对VGA、键盘/鼠标IO都熟,那咱们直接切入正题——x86_64和x86的内存映射确实不一致,而且差异还不小,下面我给你拆解清楚:
1. 核心差异:地址空间与区域划分
32位x86的内存映射
不管是实模式还是保护模式,32位x86的地址空间上限是4GB(PAE扩展后物理地址能到36位,但虚拟地址还是32位):
- 实模式:经典的1MB地址空间,前640KB是常规DOS内存,
0xA0000~0xBFFFF是VGA显存区,0xC0000~0xFFFFF是ROM/BIOS固件区域。 - 保护模式(比如Linux这类OS):通常把4GB分成3GB用户空间(
0x00000000~0xBFFFFFFF)和1GB内核空间(0xC0000000~0xFFFFFFFF),内核空间里包含直接映射的物理内存、PCI设备MMIO区域、内核代码段等。这种划分会导致一个问题:如果物理内存超过4GB,或者MMIO设备占用了低4GB的上部区域,可用的物理内存会被“吃掉”一部分。
x86_64的内存映射
x86_64用的是长模式,虚拟地址位宽是48位(部分CPU支持57位,但主流是48位),直接把地址空间劈成了完全分离的两部分:
- 用户空间:
0x0000000000000000~0x00007FFFFFFFFFFF,整整128TB,用来放用户进程的代码、栈、堆等。 - 内核空间:
0xFFFF800000000000~0xFFFFFFFFFFFFFFFF,也是128TB,完全独立于用户空间,中间有个巨大的“空洞”(0x0000800000000000~0xFFFF7FFFFFFFFFFF)用来防止用户空间越界访问内核。 - 内核空间内部又细分了几个关键区域:
- 直接映射物理内存:通常是前1GB(可配置),地址从
0xFFFF800000000000开始,把物理内存直接映射到内核空间,方便内核快速访问。 - 动态映射区(vmalloc):用来映射不连续的物理内存块,地址范围
0xFFFF880000000000~0xFFFFC7FFFFFFFFFF。 - 设备MMIO区:所有硬件设备的IO地址都映射到这里(
0xFFFFC80000000000~0xFFFFE7FFFFFFFFFF),不再占用低地址空间,彻底解决了32位下的内存空洞问题。 - 内核代码/数据段:放在最高位的地址区域,确保和用户空间完全隔离。
- 直接映射物理内存:通常是前1GB(可配置),地址从
2. 关键技术规格对比
| 维度 | 32位x86(保护模式) | x86_64(长模式) |
|---|---|---|
| 虚拟地址宽度 | 32位(4GB) | 48位(256TB总空间,分128TB用户/内核) |
| 物理地址支持 | 32位(4GB),PAE下36位(64GB) | 最高52位(4PB,取决于CPU型号) |
| 用户/内核空间划分 | 共享4GB(3GB用户+1GB内核) | 完全分离的两个128TB空间 |
| MMIO区域位置 | 内核空间的高地址部分(占用低4GB) | 内核空间的专用高地址区域 |
| 页表结构 | 两级页表,PAE下三级 | 四级页表(支持2MB/1GB大页) |
3. 对你的内核移植的实际影响
如果你想把32位的VGA/键盘/鼠标内核移植到x86_64,需要注意:
- 不能再直接用实模式的地址(比如
0xA0000访问VGA显存),长模式下要改用内核空间里的MMIO映射地址。 - 页表的构建逻辑完全不同,x86_64需要创建四级页表(PML4、PDPT、PD、PT),而32位是两级/三级。
- 内存访问权限的控制更严格,用户空间和内核空间完全隔离,不能像32位那样通过地址直接跨区域访问。
内容的提问来源于stack exchange,提问作者user135142
相关产品推荐
相关产品推荐

