目 录
1 引 言... 1
内容来自www.paper51.com
2 Linux内存管理技术... 1 copyright paper51.com
2.1 内核空间和用户空间... 1
copyright paper51.com
2.2 Linux内存管理器分类及分析... 2
内容来自www.paper51.com
2.3 Linux虚拟内存技术.... 3 内容来自www.paper51.com
3 页面置换算法... 6 http://www.paper51.com
3.1 先进先出页面置换算法—FIFO.. 6
copyright paper51.com
3.2 最近最少使用页面置换算法—LRU.. 6
内容来自论文无忧网 www.paper51.com
3.3 其他置换算法... 6 http://www.paper51.com
4 置换算法程序代码分析... 7
copyright paper51.com
4.1 说明... 7 内容来自www.paper51.com
4.2 程序代码详细分析... 7
paper51.com
4.3 输出结果及分析... 11
内容来自论文无忧网 www.paper51.com
4.4 置换算法过程演示... 12
内容来自论文无忧网 www.paper51.com
5 总 结... 13 http://www.paper51.com
参考文献... 14
http://www.paper51.com
致 谢... 14
copyright paper51.com
http://www.paper51.com
1 引 言 http://www.paper51.com
操作系统中的内存管理单元负责管理整个系统的物理地址空间和虚拟地址空间,进行虚实地址之间的转换以及页面的置换等操作。它是系统内核中最重要的组成部分之一,是整个系统得以存在和运行的基础。[1]一个高效的内存管理系统不仅要能够有效地管理系统内存,减少频繁分配和回收内存而导致的内存碎片,还要尽量提高分配和回收的速度来提高系统的运行效率和保证内存分配和回收的公平性。本文主要介绍Linux内存管理技术,包括Linux五大内存管理器及其分析、虚拟内存管理及实现机制、几种常见的置换算法,其中难点是虚拟内存的置换算法,最后,将会给出FIFO算法和LRU算法程序代码的详细解析。 内容来自www.paper51.com
2 Linux内存管理技术
paper51.com
2.1 内核空间和用户空间
copyright paper51.com
在Linux 中,虚拟地址空间的管理是以进程为基础来展开的。整个可编址内存区(在32位平台上是4GB)分为两个主要部分——内核空间和用户空间(或称为应用程序空间)。 PAGE_OFFSET定义了这两个部分的分界线,这个值是可以修改的,它定义在头文件中。内核空间位于分界线的上面,而用户空间则位于分界线之下。PAGE_OFFSET在Intel平台上的默认值是0xc0000000,也就是说,它给内存提供了大约1GB的内存空间,剩下3GB供用户空间使用[2]。Linux虚拟内存管理机制将其分开,这样不仅有效的保护了核心空间,各个进程之间也互不影响。
内容来自www.paper51.com
copyright paper51.com
图1 可编址内存区[2] 内容来自www.paper51.com
在Linux中,内核空间是靠内核段来描述的,内核段包括数据段和代码段.它被定义在全局描述符表(GDT)中,用来映射3GB到4GB的线性空间,这部分虚拟空间可由内核页目录表swapper_Pg_dir来寻址.swapper_pg_dir包含有虚拟地址从0xc0000000到0xc0000000+end_mem 的内存映射,这段空间的大小是实际物理内存的大小。swapper_pg_dir的前768项全被置为0(空),这768项可映射0至3GB线性空间,而768项以上的项指向内核页表,通过这些页表可指向实际的物理内存空间。类似地,在用户模式下每个进程都有一个局部描述符表(LDT),它包括一个代码段、一个数据段和一个堆栈段,这些用户段的线性地址可以从0到3GB。
内容来自www.paper51.com
在此,为了加深对用户空间和内核空间的理解,说明以下问题: 内容来自www.paper51.com
(1)通常情况下,用户进程只能访问用户空间的虚拟地址,不能访问内核空间虚拟地址。只有用户进程进行系统调用(代表用户进程在内核态执行)时才可以访问到内核空间。
内容来自论文无忧网 www.paper51.com
(2)用户空间对应进程,所以每当进程切换,用户空间就会跟着变化;而内核空间是由内核负责映射,它并不会跟着进程改变,是固定的。内核空间地址有自己对应的页表,用户进程各自有不同的页表。 http://www.paper51.com
(3)每个进程的用户空间都是完全独立、互不相干的。
copyright paper51.com
2.2 Linux内存管理器分类及分析 copyright paper51.com
内存管理是十分复杂的工作,Linux将内存管理的工作分配给几个不同的内存管理器。这些内存管理器各司其职,相互配合,共同完成对内存的管理工作。Linux设置了5个内存管理器,它们分别是[3,4]:
copyright paper51.com
(1)物理内存管理器。物理内存管理器是内存管理的基础,负责物理内存的分配、释放和回收,以页为单位进行管理,其目的是提高性能、减少碎块。
copyright paper51.com
衡量内存管理器算法优劣的主要标准是利用率和效率。但其中存在着这样一个矛盾:内存利用率高的算法其效率不一定高;反之,效率高的算法,其内存利用率又可能很低。所以,Linux采用了一个折中的办法:以物理内存管理器以页为单位使用伙伴算法 (Buddyalgorithm)实现高效率地分配和回收物理内存,并可避免内存碎块的产生。由内核内存管理器在物理内存管理器的基础上向其用户(内核)提供各种大小不等的物理内存,从而提高物理内存的利用率。由虚拟内存管理器在物理内存管理器的基础之上为其用户进程提供很大的虚拟空间[3-4]。 内容来自www.paper51.com
(2)内核内存管理器。由于物理内存管理器过于粗放,而内核在很多时候需要小块内存用于建立各种管理结构,所以Linux提供了内核内存管理器,专门负责内核中小块内存的分配和释放。Linux的内核内存管理器采用Slab算法。 内容来自www.paper51.com
在slab方法中每种重要的数据结构都有自己专用的缓冲区队列,每种数据结构都有相应的构造函数和析构函数。同时,还借用面向对象程序设计技术中的名词,不再称结构而称为对象。缓冲区队列中的各个对象在建立时用其构造函数进行初始化,所以一旦分配立即就能使用,而在释放时则恢复成原状。同时,有定期地检查,并加以精简。slab管理方法还有一个特点,每种对象的缓冲区队列并非由各个对象直接构成,而是由一连串的“大块”构成,而每个大块中则包含了若干同种的对象。
内容来自论文无忧网 www.paper51.com
(3)虚拟内存管理器。虚拟内存管理器在物理内存管理器的基础之上,是内存管理的核心。它通过页目录、页表核交换机制,为系统中每一个进程模拟了一个大小相等的虚拟地址空间。
内容来自www.paper51.com
Linux继承了Unix的分页管理机制,在分页系统中,物理地址和线性地址都分为固定大小的页,同时引入页表来实现线性地址到物理地址的转换。地址的转换由硬件完成,转换所用的页表由操作系统来进行维护。由于线性地址空间和物理空间之间引入了页表,隔离了两个地址空间,所以一个程序可以在物理内存中不连续,甚至程序的大部分都可以不在物理内存中。操作系统负责在内外存之间交换页面,满足每一个进程小小的“虚荣心”,让每一个进程都认为自己是系统中唯一的一个程序,自己可以独享系统的全部地址空间,而且其大小“随心所欲”,不受物理内存的限制。 内容来自www.paper51.com
(4)内核虚拟内存管理器。为了满足内核对大内存的要求,Linux利用虚拟内存管理的思想,在内核虚拟地址空间实现了内核虚拟内存管理器。[4] copyright paper51.com
(5)用户空间内存管理器。该管理器负责用户虚拟内存的动态分配和回收,它管理的内存在进程的堆中。用户空间内存管理器一般在库中实现,不属于内核,但内核为其提供相应的支持。
内容来自www.paper51.com
用户内存空间管理器是由Glibc提供支持的,它是GNU的c库。glibc提供了一组函数,为用户进程使用内存提供了方便地接口。C程序运行过程中主要涉及三种内存分配方式:静态分配、自动分配和动态分配。C语言自身支持两种重要的内存分配方式:静态分配和自动分配。除此之外,GNU C库函数中有一些函数可以动态地分配与回收可变大小的内存,这些函数包括malloc,calloc,free,realloc等。
paper51.com
几个内存管理器之间的关系如图: 内容来自www.paper51.com
paper51.com
这五个部分组成了整个Linux内存管理器,其中物理内存管理器是整个内存管理器的基础,虚拟内存管理器是核心。其它内存管理器都是在物理内存管理器的基础之上进行管理的,而各个管理器又都离不开内核内存管理器的支持。 paper51.com
2.3 Linux虚拟内存技术 http://www.paper51.com
虚拟内存通过在各个进程之间共享内存,而使系统看起来内存容量远远大于实际容量。Linux支持虚拟内存,即将计算机的 RAM 和硬盘上的临时空间组合在一起,使可用内存相应的扩大。核心是把当前不用的内存块存到硬盘,腾出内存用作他用。当原来的内容又要使用时,再读回内存。
内容来自论文无忧网 www.paper51.com
(1)Linux虚拟内存管理 copyright paper51.com
Linux虚拟内存主要由四个模块组成,如下图所示: 内容来自www.paper51.com
内容来自www.paper51.com
1)MMAP 内存映射模块 内容来自论文无忧网 www.paper51.com
负责把磁盘文件或交换空间文件的逻辑地址映射到虚拟地址以及把虚拟地址映射到物理地址。 http://www.paper51.com
2)SWAP 交换模块 内容来自www.paper51.com
负责控制内存内容的换入和换出。采用交换机制,使得在物理内存的页中保留有效的逻辑页及从主存中淘汰最近没被访问的逻辑页,保存近来访问过的逻辑页。 paper51.com
3)CORE 核心内存管理模块
内容来自www.paper51.com
负责核心内存管理功能,如页的分配、回收和请求调页处理等功能。这些功能将被别的内核子系统(如文件系统)所使用。 copyright paper51.com
4)结构特定模块
http://www.paper51.com
负责给各种硬件平台提供通用接口,通过执行命令来改变硬件MMU的虚拟地址,主要完成主存初始化工作及对页面故障的处理。这个模块是实现虚拟内存管理的基础。
paper51.com
(2)Linux虚拟内存管理功能
copyright paper51.com
1)巨大的寻址空间
内容来自论文无忧网 www.paper51.com
这是指linux操作系统让系统看上去比实际内存大很多,使得虚拟内存可以是系统中实际物理空间的许多倍。每个进程运行在其独立的虚拟地址空间中,这些虚拟空间相互之间都完全隔离开来的,所以进程间不会互相干扰[5]。 http://www.paper51.com
2)进程的保护
paper51.com
系统中的每一个进程都有自己的虚拟地址空间。这些虚拟地址空间是完全分开的,这样一个进程的运行不会影响其它进程,并且硬件上的虚拟内存机制是被保护的,内存不能被写入。
http://www.paper51.com
3)公平的物理内存分配
http://www.paper51.com
如上文中提到的,一个高效的内存管理子系统要保证内存分配和回收的公平性,所以内存管理子系统允许系统中每个运行的进程公平地共享系统中的物理内存。
paper51.com
4)共享虚拟内存 copyright paper51.com
尽管虚拟内存允许进程有其独立的虚拟地址空间,但有时也需要在进程之间共享内存。例如,有可能系统中有几个进程同时运行BASH命令外壳程序。为了避免在每个进程的虚拟内存空间内都存在BASH程序的拷贝,较好的解决办法是系统物理内存中只存在一份BASH的拷贝,并在多个进程间共享。动态库则是另外一种进程间共享执行代码的方式。共享内存可用来作为进程间通信(IPC)的手段,多个进程通过共享内存来交换信息。Linux支持SYSTEM V的共享内存IPC机制[5]。
copyright paper51.com
(3) Linux虚拟内存实现机制 copyright paper51.com
Linux虚拟内存的实现需要6种机制的支持,分别是:地址映射机制;内存分配和回收机制;缓存和刷新机制;请页机制;交换机制;内存共享机制。这几种机制的关系如图所示:
http://www.paper51.com
copyright paper51.com
首先内存管理程序通过映射机制(MMAP)把用户逻辑地址映射到物理地址,如果发现程序的虚拟地址没有对应的物理内存时,发送请页要求1;如有空闲内存可供分配,就请求分配内存CORE(内存的分配和释放)2;并把正在使用的物理页记录在页缓存中(使用了缓存机制)3;如果没有足够内存可供分配,就用交换机制(SWAP),腾出空间4、5;交换机制要用到交换缓存6,把物理页内容转换到交换文件中后也要修改页表来映射文件地址7;另外在地址映射中要通过TLB(转换后备缓冲区)来寻找物理页8。 paper51.com