浅谈LINUX 内存分页机制(by liukun321咕唧咕唧)

来源:互联网 发布:实施网络攻击的前提 编辑:程序博客网 时间:2024/05/17 03:18

    以前看过《深入理解linux内核》一书对有关内存管理的分析,但是当时对linux所知甚少,弄了个云里雾里,就那么草草过去了。今天看LDD3的时候在分配内存这章貌似又看见了它的影子,再结合前面看的《深入理解linux内核》,好像对它有了些重新的认识。下面就浅要分析一下内存分页机制:

    每个进程都拥有4G(2的32次方)的虚拟地址空间。在实际编程过程中,指针中存放的地址也都是32位的线性地址(虚拟地址),经过页目录、页表等分页机制变换以后可以得到真正的物理地址,而这个物理地址也是32位的。对于32位的CPU来说没有任何问题,因为它的地址总线是32位的,寻址空间也就是2的32次方(4G)。那么问题就出来了:CPU的寻址空间是2的32次方(4G),程序要访问的物理地址(线性地址经过分页机制变换以后得到地址)也是32位的,这种情况下的内存应该至少是4G才对,而平时我们自己用的计算机才一两个G(比如说就1个G),那么这时候的内存是怎么编址的呢(1G内存只要30根地址线就够了,相应的的物理地址位数只要30位就行了,用不了32位啊)?

    这是csdn网友的一个提问,的确1G的物理内存虚拟出4G的虚拟内存,进程在使用内存时额外的3G空间是哪来的呀?这时内存分页机制就发挥它的功效了。

我们知道在内核空间kmalloc函数和__get_free_page函数使用的地址范围(虚拟地址)和物理内存的地址范围是一一对应的。两者只是相差一个偏移(offset)。这是一种线性地址。若我们用vmalloc函数则不然,它所分配的物理内存在地址上是不连续,对于这些不连续地址的管理linux hacker通过创建struct page数据结构来实现。也就是我们所说的页表。

ps:在ARM处理器中32位的线性地址被分为3段:

  [31:22]存放页目录项地址,即存放要寻址的内存在 页目录表 的第几项,页目录表中的每项称为页目录项,也目录项中存放的是页表的地址(指物理地址)  
  [21:12]存放页表项地址,即内存在 页表 的第几项,页表的每项称为页表项,页表项存放的是该页的物理地址
  [11:0]存放页内偏移地址,通过该值就可以在上面所述的页中找到内存

页目录表地址存放在CP15协处理器中。

而线性地址空间与物理地址空间大小不一致,这才导致产生了分页机制。

      当需要使用不在物理内存中的页面时,会产生请求调页,然后操作系统负责内存页的换入换出。当线性地址转换到物理地址,而物理地址不足4G(比如1G),操作系统可以给你分配内存。你在线性地址空间得到了需要的内存,而物理内存上通过换页机制也可以满足。(假如你想使用3G开始的1页地址空间,操作系统会把任意空闲的1页内存给你使用)若真正意义上的内存只有1G。4G到1G,必须得借用硬盘空间。而一个线性地址对应一个物理地址。一个物理地址可能对应好几个线性地址。但是,使用中的那个会被放在内存,不使用的放在硬盘。由于程序的所谓“局部性”原理,一般这样做不会有问题。当同时使用内存需求大于1G时,机器就会“很卡”,因为操作系统不断地在换入换出内存页。


原创粉丝点击