linux虚存管理机制

来源:互联网 发布:lt1953wa淘宝 编辑:程序博客网 时间:2024/05/18 18:52

Linux的内存管理采用页式管理,使用多级页表,动态地址转换机构与主存、辅存共同实现虚拟内存:每个用户进程拥有4GB的虚拟地址空间,进程在运行过程中可以动态浮动和扩展,为用户提供了透明的、灵活有效的内存使用方式,下面简述Linux虚存管理以基本特点和主要实现技术:

一、 Linux虚存管理的基本特点 

1. 更大的地址空间。 
虚拟内存可以是系统实际拥有的物理内存的若干倍。因而它使得操作系统看起来拥有比实际大得多的内存。 
2. 合理的物理内存分配。 
Linux通过共享和交换策略,使各个运行的进程能公平地共享内存。 3. 保护。 
Linux存储管理子系统为每一内存页设置了“上锁位”,在线性地址及每级页表页项上设置了“读/写”位,这样来确保某一个进程不受其他进程的干扰。即使某一个进程失败了,也不会影响到其他进程和操作系统本身。 
4. 共享虚拟内存 
Linux实现的虚拟内存允许两个进程之间互相共享内存,例如:共享的库。在这种情形之下,库代码仅存在于一个进程,而不需要为每一个应用都复制一份。

二、 Linux虚存管理的主要实现技术 

1、 请求调页(demanding paging)与内存扩展 

用户进程创建时,并不是将它所需所有页都分配给相应物理页。开始时只装入页面中进程的第一个页面,其他页根据进程运行过程的请求从外存调入所需页面,当进程访问一个页表项P位为0的页中地址时,表示此页不在主存中,将产生缺页中断,系统调用 handle_mm_fault()处理访问异常,为之分配相应物理页后,它再调用swap_in()函数,从外存中读入该页面。 
Linux是一种请求式分页存贮管理,这才使之可以运行大于主存空间的进程。

2. 页换出策略

内存中页面不足时,Linux采用最近最少使用(LRU)算法:即每次换出时,总是选择最老的页换出,对易于从其他设备上获取的非脏(not dirty)页面。Linux采用丢弃(discarding)技术,如果发生过写操作,则将该页写入系统的Swapfile中,这样就可以加快换入的速度。

3、 内存共享 

Linux将内存划分为4K大小的页面,为内存共享提供了基础: 
 (1)不同进程间页面共享时,可令共享该页的进程的页表项(pte)均指向该页。
 (2)对kernel代码和数据段的共享,通过进程创建时fork() 函数将kernel代码和数据段映射到用户虚存的3GB~4GB的空间中去,所以每个进程都可以通过一定方式共享kernel的代码和数据段。

4、 内存保护 

采用了“Hole”技术、虚存段的保护、地址转换机构、页表存取控制位(R/W位)等技术实现了内存保护。 
1)“Hole”技术  物理内存前4K是一空页(empty_zero_page),用来捕获NULL指针的异常访问。在进程每个虚存段后,都有一个“4K”的“Hole”,用来捕获虚存段的越界访问。(在C语言的内存布局中,Hole存在与栈与堆之间)
2) 虚存段保护方式  主存中虚存段的全部或部分可以设为保护方式,防止非法访问。 、
3) 页表项存取控制位(R/W位)  页表项以“R/W”位表示此页的存取权限“1”为可读写,“0”为不可读写,可用来防止越权访问。 
4) 地址转换机构 ,分页存贮管理方法中,地址转换机构进行的页面映象实际上防止了各进程的主存块间互不干扰,起到进程隔离的作用
 

5、 动态地址变换 

利用i386的地址变换机构(逻辑地址转换为物理地址--由MMU来实现)Linux实现了动态地址变换,进程执行时访问到某一虚拟地址时才确定其对应的物理地址。这种方式为进程存贮块的动态和动态扩展提供了基础。

三. linux虚存管理的主要数据结构

1、32-bit虚拟地址

在Linux 中,4GB的虚存需通过32-bit 地址进行寻址。(Linux 中虚拟地址与线性地址是同一个概念)虚拟地址被分割成3 个子位段,其中2 个子位段包含10 位, 1 个子位段包含12 位

 

3个子位段分别表示不同含义:子位段1 指向被称作页目录(PGD)的一张表,子位段2 指向被称作页表(PTE)的一张表,子位段3 指向页内地址。

2. linux多级页表结构

标准的Linux的虚存页表为三级页表,依次为页目录(Page Directory--PGD)、中间页目录(Page Middle Directory--PMD)、页表(Page Table)—PTE)。

在i386机器上Linux的页表结构实际为两级,PGD和PMD页表是合二为一的。所有有关PMD的操作实际上是对PGD的操作。所以原代码中形如*-pgd-*()和*-pmd-*()的函数实现的功能也是一样的。

页目录(PGD) 是一个大小为4K 的表,每一个process只有一个页目录,以4 字节为一个表项,分成1024 个表项(或称入口点);该表项的值为所指页表的始地址。32位虚拟地址的第1 个子位段共10 位,其值的范围从0 到1023,对应于页目录的一个入口点。

页目录(PTE)的每一个入口点的值为此表项所指的一页框(page frame),32位虚拟地址的第2 个子位段共10 位,其值的范围从0 到1023。

页框(page frame)并不是物理页,它指是虚存的一个地址空间。

3、页表项的格式

Linux中页表每一个表项的格式,如图所示


其中,各位段的含义如下:

P :

存在位,表示该表项对地址的转换是否有效。i386 处理器在P=0 时不解释表项中的任何位,此时这些位的含义完全由软件自行解释。P 位提供了至关重要的属性,以支持分页机制。如果P=1,则表示虚拟地址所对应的页框存在于物理内存中,访问该虚拟地址的程序可以正常运行;P=0,则表示虚拟地址所对应的页框不存在于物理内存中,访问该虚拟地址的程序将会引发页访问异常,产生缺页中断。使得Operating System 可以把缺少的页从磁盘上读入内存,并将读入页存入到表项中,然后将该页标志为存在,再使引起异常的程序继续执行。

R/W :

读写位,表示对该表项指向的页可以进行读、写或执行操作。R/W=1 则该页可写,可读,且可执行;R/W=0 则该页可读,可执行,但不可写。当处理器处于特权级0~2时,R/W位被忽略。如该表项位于页目录中,则作用于该表项映射的所有各页。

U/S :

用户/系统位。U/S=1 则该页可在任何处理器特权级下访问;U/S=0 则该页只能在处理器特权级0~2下被访问。如该表项位于页目录中,则作用于该表项映射的所有各页。

D :

已写标志位。在对该表项映射的页进行写访问之前,处理器对该位置1。如该表项是页目录中表项,处理器不修改D位。

Address :

页框物理地址的高20位。系统将物理内存分割成4K大小的内存页框,Address实际上代表了页框的帧号。


4、动态地址映射

Linus虚存采用动态地址映射方式,即进程的地址空间和存储空间的对应关系是在程序的执行过程中实现的:进程每用到一个地址时, 都需虚存的地址转换机构把虚拟地址转化为内存的实际地址。其地址映射如下图所示:


动态地址映射使Linux可以实现进程在主存中的动态重定位,虚存段的动态扩展和移动;也为虚存的实现提供了基础。