为何需要虚拟地址映射?
这个问题其实牵涉到在内存布局中,内核放在逻辑高地址还是低地址?在内核启动过程,虚拟地址映射不是必要的,默认可以理解为实地址和虚拟地址一一映射(当然还有别的复杂的情况,暂不考虑),比如FreeNOS
就是将内核直接映射在逻辑内存低地址处。
-
放在低地址的优点在于编译链接内核时候直接用实地址即可,内存管理相关相对直观一点。而缺点就是编译用户态进程的时候,载入地址
(entry point)
略微反直觉(就比如是0x80000000
)。 -
放在高地址的优缺点恰好与低地址的相反,内存管理上抽象复杂许多,优点也仅是用户态进程的
entry point
符合直觉(一般就是0x0
地址)
总的来说两者都可以,只不过为了与xv6
和linux
对齐,并且增加点难度,我这边选择了将内核放在高地址。
具体怎么做?
最终目标简单来说就是,将原来上一章中的载入地址加上一个偏移KERNEL_BASE
即可,这样做的最大好处是便于内核态做虚实地址的切换。也就是内核态的地址映射遵循简单的数学公式虚拟地址 = 实地址 + KERNEL_BASE
实现的思路
- 1、编译链接时候全部使用虚拟地址,也就是在
kernel.ld
中指定了KERNEL_BASE
- 2、在启动时候,预先进行虚拟地址映射,假定编译出来的内核最终体积小于
8M
,那么映射范围就是[0, 8M] -> [KERNEL_BASE, KERNEL_BASE + 8M]
最终如何实现依赖于各个处理器的MMU
,就比如x86
的页管理机制,具体在后续内存管理章节会详细展开,这章节深究会导致本末倒置。