Linux
中有以下几种内存地址类型:
(1)User virtual addresses
:
用户空间程序(user-space program
)所看到和使用的地址。这些都是虚拟地址(virtual address
),需要经过转化后,才能变成实际的内存物理地址。每个进程都拥有自己的虚拟地址空间。
(2)Physical addresses
:
实际的内存物理地址,也即是CPU
用来访问物理内存的地址。
(3)Bus addresses
:
总线地址。外围设备所看到的物理内存地址。通常情况下,这个地址就是实际的内存物理地址。但是如果系统支持IOMMU
的话,总线地址和实际的内存物理地址之间需要做一个映射。
(4)Kernel logic addresses
:
内核逻辑地址。内核逻辑地址会部分或全部地映射到物理内存地址,所以看起来就像实际的物理内存地址一样,并且这种映射是线性的,一对一的。在许多体系结构上,内核逻辑地址和物理内存地址只差一个常量偏移。内核虚拟地址的值通常存储在指针类型或unsigned long
类型的变量里。kmalloc
函数返回的就是内核逻辑地址。
(5)Kernel virtual addresses
:
内核虚拟地址。内核虚拟地址同内核逻辑地址相似的地方是都是把内核地址空间和实际物理内存的地址空间做映射,不同之处在于内核虚拟地址不要求这种映射是线性的,一对一的。内核逻辑地址都是内核虚拟地址,但是反过来则不成立。内核虚拟地址的值通常存储在指针类型变量里。vmalloc
和kmap
返回的都是内核虚拟地址。
__pa
(定义在<asm/page.h>
)宏用来把内核逻辑地址映射为实际的内存物理地址;__va
则用来把实际的内存物理地址映射为内核逻辑地址(仅限于low memory
)。