现在的位置: 首页 > 综合 > 正文

Linux虚拟内存管理机制,交换和请求分页存储管理技术

2013年10月15日 ⁄ 综合 ⁄ 共 2713字 ⁄ 字号 评论关闭

From: http://blog.sina.com.cn/s/blog_4cbc6fdd01000ap2.html


Linux系统采用了虚拟内存管理机制,就是交换和请求分页存储管理技术。这样,当进程运行时,不必把整个进程的映像都放在内存中,只需在内存保留当前用到的那一部分页面。当进程访问到某些尚未在内存的页面时,就由核心把这些页面装入内存。

请求分页机制

分页存储管理的基本方法如下:

(1)逻辑空间分页
将一个进程的逻辑地址空间划分成若干个大小相等的部分,每一部分称作页面或页。每页都有一个编号,叫做页号,页号从0开始依次编排,如0、1、2...

(2)内存空间分页
把内存也划分成与页面相同大小的若干个存储块,称作内存块或内存页面。同样,它们也进行编号,内存块号从0开始依次顺序排列:0#块、1#块、2#块....
页面和内存块的大小是由硬件确定的,它一般选择为2的若干次幂。不同机器中页面大小是有区别的。在x86平台上的Linux系统的页面大小为4KB。

(3)逻辑地址表示
地址由两个部分组成,前一部分表示该地址所在页面的页号p;后一部分表示页内位移d,即页内地址。两部分构成的地址长度为32位,其中0~11为页内位移,即每页的大小为4KB;12~31位为页号,表示地址空间中最多可容纳1M个页面。

(4)内存分配原则
在分页情况下,系统以内存块为单位把内存分给作业或进程,并且一个进程的若干页可分别装入物理上不相邻的内存块中。

(5)页表
在分页系统中允许将作业或进程的各页面离散地装入内存的任何空闲块中,这样一来就出现作业的页号连续、而块号不连续的情况。怎样找到每个页面在内存中对应的物理块呢?为此,系统又为每个进程设立一张页面映像表,简称页表。

 

请求分页存储管理技术是在简单分页技术基础上发展起来的,二者根本区别在于请求分页提供虚拟存储器。它的基本思想是,当要执行一个程序时才把它换入内存;但并不把全部程序都换入内存,而是用到哪一页时才换入它。这样,就减少了对换时间和所需内存数量,允许增加程序的道数。
为了表示一个页面是否已装入内存块,在每一个页表项中增加一个状态位,Y表示该页对应的内存块可以访问;N表示该页不对应内存块,即该页尚未装入内存,不能立即进行访问。如果地址转换机构遇到一个具有N状态的页表项时,便产生一个缺页中断,告诉CPU当前要访问的这个页面还未装入内存。操作系统必须处理这个中断:它装入所要求的页面,并相应调整页表的记录,然后再重新启动该指令。
由于这种页面是根据请求而被装入的,所以这种存储管理方法叫做请求分页存储管理。通常在作业最初投入运行时,仅把它的少量几页装入内存,其它各页是按照请求顺序动态装入的,这样就保证用不到的页面不会被装入内存。


Linux 的多级页表
在x86平台的Linux系统中,地址码采用32位,因而每个进程的虚存空间可达4GB。Linux内核将这4GB的空间分为两部分:最高地址的1GB是“系统空间”,供内核本身使用;而较低地址的3GB是各个进程的“用户空间”。

系统空间由所有进程共享。虽然理论上每个进程的可用用户空间都是3GB,但实际的存储空间大小要受到物理存储器 (包括内存及磁盘交换区或交换文件) 的限制。
由于Linux系统中页面大小为4KB,因此进程虚存空间要划分为1M个页面。如果直接用页表描述这种映射关系,那么每个进程的页表就要有1M个表项。很显然,用大量的内存资源来存放页表的办法是不可取的。为此,Linux系统采用三级页表的方式。

PMD表示中间目录,PT表示页表。一个线性的虚拟地址在逻辑上从高位到低位划分成4个位段,分别用作页面目录PGD中的下标、中间目录PMD中的下标、页表PT中的下标和物理页面(即内存块)内的位移。
这样,把一个线性地址映射成物理地址分为以下四步:
(1) 以线性地址中最高位段作下标,在PGD中找到相应的表项,该表项指向相应的PMD。
(2) 以线性地址中第二个位段作下标,在PMD中找到相应的表项,该表项指向相应的PT。
(3) 以线性地址中第三个位段作下标,在PT中找到相应的表项,该表项指向相应的物理页面(即该物理页面的起始地址)。
(4) 线性地址中的最低位段是物理页面内的相对位移量,此位移量与该物理页面的起始地址相加就得到相应的物理地址。
地址映射是与具体的CPU和MMU(内存管理单元)相关的。对于i386来说,CPU只支持两级模型,所以,实际上跳过了中间的PMD这一级。从Pentium Pro开始,允许将地址从32位提高到36位,并且在硬件上支持三级映射模型。


Linux系统采用位图和链表两种方法来管理内存页。

利用位图可以记录内存单元的使用情况。用一个二进制位(bit)记录一个内存页的使用情况:如果该内存页是空闲的,则对应的位是1;如果该内存页已经分配出去,则对应的位是0。例如有1024KB的内存,内存页的大小是4KB,则可以用32个字节构成的位图来记录这些内存的使用情况。


分配内存时就检测该位图中的各个位,找到所需个数的连续位值为1的位图位置,进而就获得所需的内存空间。利用链表可以记录已分配的内存单元和空闲的内存单元。采用双向链表结构将内存单元链接起来,从而可以加速空闲内存的查找或链表的处理。


利用链表可以记录已分配的内存单元和空闲的内存单元。采用双向链表结构将内存单元链接起来,从而可以加速空闲内存的查找或链表的处理。Linux系统的物理内存页分配采用链表和位图相结合的方法,数组free_area的每一项描述某一种内存页组(即由相邻的空闲内存页构成的组)的使用状态信息。
其中,头一个元素描述孤立出现的单个内存页的信息,第二个元素描述以两个连续内存页为一组的页组的信息,第三个元素描述以四个内存页为一组的页组的信息,依此类推,页组中内存页的数量依次按2的倍数递增。


当系统启动时,交换守护进程由内核的init(初始化)进程启动。它在一些简单的初始化操作之后便进入无限循环,在每次循环的末尾会进入睡眠。内核在一定时间以后又会唤醒并调度它继续运行,这时它就又回到该无限循环开始的地方。


交换守护进程所做的工作主要分为两部分。第一部分是在发现可用的内存页面已经短缺的情况下,则找出若干不常用的内存页面,使它们从活跃状态(至少有一个进程的页表项指向该页面)变为不活跃状态(不再有任何进程的页表项指向该页面),为页面换出作好准备。第二部分是每次都要执行的工作,把那些已经处于不活跃状态的“脏”页面(即内存页的内容与盘上页面的内容不一致)写入交换设备,使它们成为不活跃“干净”页面(内存页内容与盘上页面内容一致)继续缓冲,或者进一
步回收一些内存页,使之成为空闲的内存页。

抱歉!评论已关闭.