Linux中使用的地址类型列表:
用户虚拟地址(User virtual addresses)
用户空间程序可见的普通地址。用户虚拟地址的长度为32位或64位,依赖于底层的硬件体系架构,每个进程有它自己的虚拟地址空间。
物理地址(Physical addresses)
处理器和系统内存之间使用的地址。物理地址的长度为32位或64位;32位操作系统上有时也可以使用大于32位的物理地址(PAE)
总线地址(Bus addresses)
外部总线和系统内存之间使用的地址。通常总线地址和物理地址是等同的,但也不一定。有些体系结构上,有一个IOMMU(IO memory management unit)将总线地址重映射为物理地址。IOMMU在许多场景下有帮助,比如将分散的物理内存重映射成连续的总线地址,设备看起来总线地址是连续的。但这也带来了额外的工作量,比如在DMA操作时,需要对IOMMU额外的编程(填写映射项)。当然,总线地址是和体系结构高度相关的。
内核逻辑地址(Kernel logical addresses)
内核逻辑地址组成了内核的普通地址空间。这些地址映射部分或全部主存地址,而且经常被认为它们貌似就是物理地址。在大多数体系架构上,逻辑地址和相关的物理地址之间就只差了一个固定的偏移量。逻辑地址的类型为硬件本地指针大小,因此,在32位重载的系统上,可能不能访问所有的物理地址。逻辑地址的类型通常为unsigned long或者void *。通过kmalloc分配出来的内存,地址类型为逻辑地址。
内核虚拟地址(Kernel virtual addresses)
内核虚拟地址和内核逻辑地址相似,因为它们就是内核空间地址向物理内存的映射。与内核逻辑地址不同的是,内核虚拟地址在映射时,不必线性或者一对一映射成物理地址。所有的内核逻辑地址为内核虚拟地址,但许多内核虚拟地址却不是内核逻辑地址。比如vmalloc分配出来的内存为内核虚拟地址(但未直接映射为物理地址)。kmap函数返回的也是内核虚拟地址。内核虚拟地址通常储存在指针变量中。
宏__pa()(定义在<asm/page.h>)将内核逻辑地址转换成物理地址。宏__va()将物理地址转换回内核逻辑地址,但只针对低地址生效。