个人学习笔记,可能会有错误之处,敬请谅解。
一直以来感觉虚拟地址和物理地址之间的相互转换非常麻烦,虚拟地址到物理地址的转换由CPU硬件完成,但物理地址到虚拟地址怎么转换啊?况且有时候在软件上也希望通过一个虚拟地址得到物理地址,这时候自然不能依赖CPU的硬件了,该怎么转换呢?
今天看了下Linux代码,才发现内核地址空间的地址转换其实非常简单,总结如下(Kernel: 4.5, x86_64):
物理地址到虚拟地址转换由宏 __va(x) 实现,该宏定义在arch/x86/include/asm/page.h中定义如下:
#define __va(x) ((void *)((unsigned long)(x)+PAGE_OFFSET))
怎么样,够简单吧? 就是加上一个offset而已。宏PAGE_OFFSET在arch/x86/include/asm/page_types.h中定义如下:
#define PAGE_OFFSET ((unsigned long)__PAGE_OFFSET)
宏__PAGE_OFFSET在arch/x86/include/asm/page_64_types.h中定义如下:
#define __PAGE_OFFSET _AC(0xffff880000000000, UL)
__AC也是宏定义在include/uapi/linux/const.h中: