全部博文(50)
分类: LINUX
2014-04-04 11:53:24
原文地址:Vi Linux内存 之 地址空间 作者:palals
1) 逻辑地址:logical address,由80x86架构引入这一概念,由段地址和段内偏移组成。可以把程序分为若干个段来管理,比如代码段、数据段等。
2) 线性地址:linear address,又称为virtual address,虚拟地址。32位的虚拟地址代表一个连续的4GB大小的线性地址空间,由0x0至0xFFFFFFFF。
3) 物理地址:physical address。通过物理地址来访问内存单元。
Linux非常有限的使用了段这个概念,实际上,分段机制和分页机制在功能上有很多重复的地方。通过分页机制同样能划分物理地址空间,并且能够以页为单位将虚拟地址映射到物理地址。Linux这样做的原因是:
1) 所有进程共享同样的虚拟地址空间,内存管理更加简单。
2) 许多RISC架构的CPU对段的支持很有限。
2.6版本的Linux只有在80x86架构上才使用分段机制。这里不再过多研究,下面主要介绍MIPS架构的地址空间。
先说虚拟地址空间,MIPS将虚拟地址空间分为4个部分。由低到高分别是:
1) kuseg:0x0至0x7FFFFFFF总共2G的区间。Linux用户态使用的虚拟地址区间。这部分区间需要经过动态的TLB映射才能访问到物理地址。由于是动态TLB,相同的虚拟地址在不同时间点可能对应到不同的物理地址。
2) kseg0:0x80000000至0x9FFFFFFF总共512M的区间。Linux内核态使用的虚拟地址区间。这部分区间是直接映射到低512M物理地址的,虚拟地址只需减去2G就得到了物理地址,由于映射关系极为简单,所以称之为“unmapped”区域。
3) kseg1:0xA0000000至0xBFFFFFFF总共512M的区间。也是直接映射到低512M物理地址。与kseg0的不同之处在于,kseg0是需要通过cache访问物理地址的,而kseg1不经过cache,直接访问。通常对硬件寄存器的访问都是使用kseg1区间,因为这类访问往往要求不经过cache。MIPS boot的启动入口0xBFC00000就位于kseg1空间。
4) kseg2:0xC0000000至0xFFFFFFFF总共1G的区间。也是Linux内核态使用得虚拟地址区间,与kuseg一样,需要经过动态的TLB映射才能访问到物理地址。在管理模式(supervisor mode)下将此区域分为两部分kseg2和kseg3,低半部分kseg2供管理态的程序使用。
再来看物理地址空间,Linux总体上将物理地址空间分为两部分:
1) 低端内存:0x0至0x1FFFFFFF总共512M的区间,与虚拟地址是直接映射的关系。需要注意的是,这里的“内存”指的是广义的内存。其中0至256M的物理地址区间对应到内存区域,256M至512M的物理地址区间是IO空间,对应的并不是我们通常所说的内存,而是外围设备的“内存”,比如寄存器、存储空间等,这类设备包括pci io、pci config、flash、nvram、cpld、tcam等。
2) 高端内存:0x20000000至0xFFFFFFFF总共3.5G的区间,与虚拟地址是动态映射的关系。0xFFFFFFFF只是32位物理地址空间理论上的上限,Linux内核初始化的时候会根据探测到的实际内存大小来调整上限值。比如内存条大小为2G,那么实际的高端内存上限为2G+256M=2304M。256M为低端内存中IO区间的大小。高端内存上限之上的物理地址空间也没有浪费,可以把它们分配给其他“内存”区域,比如pci memory。
LDD3中提出了内核逻辑地址(kernel logical addresses)的概念,指内核的常规地址空间,虚拟地址是直接映射到物理地址的,对MIPS而言,即kseg0和kseg1。而内核虚拟地址(kernel virtual addresses)则包含所有内核可以使用的虚拟地址空间,虚拟地址不一定是直接映射到物理地址的。显然内核虚拟地址包括内核逻辑地址,对MIPS而言,即kseg0、kseg1和kseg2。