操作系统管理内存的机制——为什么要设置虚拟内存?
转自:http://blog.163.com/redhumor@126/blog/static/1955478420113249937688/
在进入正题前先来谈谈操作系统内存管理机制的发展历程,了解这些有利于我们更好的理解目前操作系统的内存管理机制。
一 早期的内存分配机制
在早期的计算机中,要运行一个程序,会把这些程序全都装入内存,程序都是直接运行在内存上的,也就是说程序中访问的内存地址都是实际的物理内存地址。当计算机同时运行多个程序时,必须保证这些程序用到的内存总量要小于计算机实际物理内存的大小。那当程序同时运行多个程序时,操作系统是如何为这些程序分配内存的呢?下面通过实例来说明当时的内存分配方法:
某台计算机总的内存大小是128M,现在同时运行两个程序A和B,A需占用内存10M,B需占用内存110。计算机在给程序分配内存时会采取这样的方法:先将内存中的前10M分配给程序A,接着再从内存中剩余的118M中划分出110M分配给程序B。这种分配方法可以保证程序A和程序B都能运行,但是这种简单的内存分配策略问题很多。
图一 早期的内存分配方法
问题1:进程地址空间不隔离。由于程序都是直接访问物理内存,所以恶意程序可以随意修改别的进程的内存数据,以达到破坏的目的。有些非恶意的,但是有bug的程序也可能不小心修改了其它程序的内存数据,就会导致其它程序的运行出现异常。这种情况对用户来说是无法容忍的,因为用户希望使用计算机的时候,其中一个任务失败了,至少不能影响其它的任务。
问题2:内存使用效率低。在A和B都运行的情况下,如果用户又运行了程序C,而程序C需要20M大小的内存才能运行,而此时系统只剩下8M的空间可供使用,所以此时系统必须在已运行的程序中选择一个将该程序的数据暂时拷贝到硬盘上,释放出部分空间来供程序C使用,然后再将程序C的数据全部装入内存中运行。可以想象得到,在这个过程中,有大量的数据在装入装出,导致效率十分低下。
问题3:程序运行的地址不确定。当内存中的剩余空间可以满足程序C的要求后,操作系统会在剩余空间中随机分配一段连续的20M大小的空间给程序C使用,因为是随机分配的,所以程序运行的地址是不确定的。
二 分段
为了解决上述问题,人们想到了一种变通的方法,就是增加一个中间层,利用一种间接的地址访问方法访问物理内存。按照这种方法,程序中访问的内存地址不再是实际的物理内存地址,而是一个虚拟地址,然后由操作系统将这个虚拟地址映射到适当的物理内存地址上。这样,只要操作系统处理好虚拟地址到物理内存地址的映射,就可以保证不同的程序最终访问的内存地址位于不同的区域,彼此没有重叠,就可以达到内存地址空间隔离的效果。
当创建一个进程时,操作系统会为该进程分配一个4GB大小的虚拟进程地址空间。之所以是4GB,是因为在32位的操作系统中,一个指针长度是4字节,而4字节指针的寻址能力是从0x00000000~0xFFFFFFFF,最大值0xFFFFFFFF表示的即为4GB大小的容量。与虚拟地址空间相对的,还有一个物理地址空间,这个地址空间对应的是真实的物理内存。如果你的计算机上安装了512M大小的内存,那么这个物理地址空间表示的范围是0x00000000~0x1FFFFFFF。当操作系统做虚拟地址到物理地址映射时,只能映射到这一范围,操作系统也只会映射到这一范围。当进程创建时,每个进程都会有一个自己的4GB虚拟地址空间。要注意的是这个4GB的地址空间是“虚拟”的,并不是真实存在的,而且每个进程只能访问自己虚拟地址空间中的数据,无法访问别的进程中的数据,通过这种方法实现了进程间的地址隔离。那是不是这4GB的虚拟地址空间应用程序可以随意使用呢?很遗憾,在Windows系统下,这个虚拟地址空间被分成了4部分:NULL指针区、用户区、64KB禁入区、内核区。应用程序能使用的只是用户区而已,大约2GB左右(最大可以调整到3GB)。内核区为2GB,内核区保存的是系统线程调度、内存管理、设备驱动等数据,这部分数据供所有的进程共享,但应用程序是不能直接访问的。
人们之所以要创建一个虚拟地址空间,目的是为了解决进程地址空间隔离的问题。但程序要想执行,必须运行在真实的内存上,所以,必须在虚拟地址与物理地址间建立一种映射关系。这样,通过映射机制,当程序访问虚拟地址空间上的某个地址值时,就相当于访问了物理地址空间中的另一个值。人们想到了一种分段(Sagmentation)的方法,它的思想是在虚拟地址空间和物理地址空间之间做一一映射。比如说虚拟地址空间中某个10M大小的空间映射到物理地址空间中某个10M大小的空间。这种思想理解起来并不难,操作系统保证不同进程的地址空间被映射到物理地址空间中不同的区域上,这样每个进程最终访问到的
物理地址空间都是彼此分开的。通过这种方式,就实现了进程间的地址隔离。还是以实例说明,假设有两个进程A和B,进程A所需内存大小为10M,其虚拟地址空间分布在0x00000000到0x00A00000,进程B所需内存为100M,其虚拟地址空间分布为0x00000000到0x06400000。那么按照分段的映射方法,进程A在物理内存上映射区域为0x00100000到0x00B00000,,进程B在物理内存上映射区域为0x00C00000到0x07000000。于是进程A和进程B分别被映射到了不同的内存区间,彼此互不重叠,实现了地址隔离。从应用程序的角度看来,进程A的地址空间就是分布在0x00000000到0x00A00000,在做开发时,开发人员只需访问这段区间上的地址即可。应用程序并不关心进程A究竟被映射到物理内存的那块区域上了,所以程序的运行地址也就是相当于说是确定的了。 图二显示的是分段方式的内存映射方法。
图二 分段方式的内存映射方法
这种分段的映射方法虽然解决了上述中的问题一和问题三,但并没能解决问题二,即内存的使用效率问题。在分段的映射方法中,每次换入换出内存的都是整个程序,这样会造成大量的磁盘访问操作,导致效率低下。所以这种映射方法还是稍显粗糙,粒度比较大。实际上,程序的运行有局部性特点,在某个时间段内,程序只是访问程序的一小部分数据,也就是说,程序的大部分数据在一个时间段内都不会被用到。基于这种情况,人们想到了粒度更小的内存分割和映射方法,这种方法就是分页(Paging)。
三 分页
分页的基本方法是,将地址空间分成许多的页。每页的大小由CPU决定,然后由操作系统选择页的大小。目前Inter系列的CPU支持4KB或4MB的页大小,而PC上目前都选择使用4KB。按这种选择,4GB虚拟地址空间共可以分成1048576个页,512M的物理内存可以分为131072个页。显然虚拟空间的页数要比物理空间的页数多得多。
在分段的方法中,每次程序运行时总是把程序全部装入内存,而分页的方法则有所不同。分页的思想是程序运行时用到哪页就为哪页分配内存,没用到的页暂时保留在硬盘上。当用到这些页时再在物理地址空间中为这些页分配内存,然后建立虚拟地址空间中的页和刚分配的物理内存页间的映射。
下面通过介绍一个可执行文件的装载过程来说明分页机制的实现方法。一个可执行文件(PE文件)其实就是一些编译链接好的数据和指令的集合,它也会被分成很多页,在PE文件执行的过程中,它往内存中装载的单位就是页。当一个PE文件被执行时,操作系统会先为该程序创建一个4GB的进程虚拟地址空间。前面介绍过,虚拟地址空间只是一个中间层而已,它的功能是利用一种映射机制将虚拟地址空间映射到物理地址空间,所以,创建4GB虚拟地址空间其实并不是要真的创建空间,只是要创建那种映射机制所需要的数据结构而已,这种数据结构就是页目和页表。
当创建完虚拟地址空间所需要的数据结构后,进程开始读取PE文件的第一页。在PE文件的第一页包含了PE文件头和段表等信息,进程根据文件头和段表等信息,将PE文件中所有的段一一映射到虚拟地址空间中相应的页(PE文件中的段的长度都是页长的整数倍)。这时PE文件的真正指令和数据还没有被装入内存中,操作系统只是根据PE文件的头部等信息建立了PE文件和进程虚拟地址空间中页的映射关系而已。当CPU要访问程序中用到的某个虚拟地址时,当CPU发现该地址并没有相相关联的物理地址时,CPU认为该虚拟地址所在的页面是个空页面,CPU会认为这是个页错误(Page Fault),CPU也就知道了操作系统还未给该PE页面分配内存,CPU会将控制权交还给操作系统。操作系统于是为该PE页面在物理空间中分配一个页面,然后再将这个物理页面与虚拟空间中的虚拟页面映射起来,然后将控制权再还给进程,进程从刚才发生页错误的位置重新开始执行。由于此时已为PE文件的那个页面分配了内存,所以就不会发生页错误了。随着程序的执行,页错误会不断地产生,操作系统也会为进程分配相应的物理页面来满足进程执行的需求。
分页方法的核心思想就是当可执行文件执行到第x页时,就为第x页分配一个内存页y,然后再将这个内存页添加到进程虚拟地址空间的映射表中,这个映射表就相当于一个y=f(x)函数。应用程序通过这个映射表就可以访问到x页关联的y页了。
相关推荐
虚拟内存管理是操作系统的核心组成部分,它为每个进程提供了一个独立的、抽象的内存视图,使得每个进程都仿佛拥有自己的一整块连续内存空间。在Linux操作系统中,虚拟内存的管理涉及多个关键概念和数据结构。 首先...
### 操作系统实验——内存管理 ...综上所述,本实验通过对内存管理的基本概念和实际操作的学习,帮助学生深入了解操作系统如何管理和优化内存资源,为后续深入研究操作系统内部机制打下了坚实的基础。
操作系统是计算机系统的核心组成部分,负责管理和控制系统的硬件资源,其中包括至关重要的内存管理。在这个实验中,我们将...通过实验,你可以深入探究这一主题,提高对操作系统内存管理的理解,并锻炼你的编程能力。
在本实验中,我们将关注以页面为单位的虚拟内存分配方法,这通常用于现代操作系统,如Linux和Windows。虚拟内存允许程序使用比实际物理内存更大的地址空间,通过将不常用的数据交换到磁盘上,从而实现内存的高效利用...
操作系统是计算机科学的基础组成部分,它负责管理和控制计算机硬件与软件资源,为用户提供一个高效、便捷的计算环境。本文将深入探讨操作系统中的核心概念,包括作业、进程、内存、设备和文件管理。 首先,我们来...
"操作系统面试题——操作系统...操作系统中还有许多其他重要的概念和知识点,包括进程状态、虚拟内存、物理地址到逻辑地址的转换、分页式管理等等。操作系统是计算机科学中的一门重要课程,需要我们认真学习和掌握。
在这个"操作系统实验——虚存管理实验"中,我们主要关注的是在Linux环境下如何实现虚拟内存的管理,以及涉及到的一些关键概念和技术。 首先,虚存管理是操作系统中的一项重要功能,它使得程序可以运行在比实际物理...
2. 内存管理:Windows 2000采用分页式虚拟内存系统,能够将硬盘上的部分文件暂时转换为内存中的“虚拟内存”,使得应用程序可以使用超过物理内存的地址空间。它还引入了写时复制技术,减少因数据共享导致的内存副本...
操作系统实验报告——存储管理 本实验报告的主要目的是为了理解内存分配原理,特别是页式虚拟内存分配方法,并了解 Windows 2000/XP 的内存管理机制,掌握页式虚拟存储技术。 一、实验目的 1. 理解内存分配原理,...
操作系统是计算机系统的核心组成部分,负责资源管理和任务调度。在基于C语言的操作系统实验中,内存管理是一个关键领域,它涉及到如何有效地...通过分析这些文件,我们可以动手实践,加深对操作系统内存管理的理解。
2. **内存管理**:包括虚拟内存、分页与分段技术、页面替换算法(如LRU、FIFO等)以及内存保护等概念。 3. **文件系统**:讲述文件的组织结构、I/O操作、磁盘调度算法,以及文件的存储与访问方式。 4. **设备管理*...
内存管理是计算机操作系统中的核心组件,它负责有效地分配和回收内存资源,确保多个进程的并发执行和系统的稳定性。本资源的“博客实验2正篇——内存管理”关注于这一主题,提供了实现内存管理的代码以及相关的图表...
《深度探索Linux操作系统——系统构建和原理解析》是一本专为那些希望深入了解Linux操作系统内核和系统构建的读者量身打造的专业书籍。它详细阐述了Linux操作系统的内部工作机制,涵盖了从内核设计到系统服务的...
为什么必须管理内存 内存管理是计算机编程最为基本的领域之一。在很多脚本语言中,您不必担心内存是如何管理的,这并不能使得内存管理的重要性有一点点降低。对实际编程来说,理解您的内存管理器的能力与局限性至关...
操作系统是计算机科学中的核心课程之一,它管理着计算机硬件资源,包括处理器、内存以及外部设备,同时也为用户提供了一个友好的接口。在这个实验中,我们将深入理解操作系统中的存储管理这一重要概念,通过编写源...
操作系统是计算机系统的核心组成部分,它负责管理和控制计算机硬件与软件资源,为用户提供高效、便捷的交互环境。在操作系统中,文件管理和存储管理是两个至关重要的领域。这些领域涉及到如何有效地组织、检索、存储...
本文主要针对Linux操作系统中的内存管理技术进行探讨,特别是针对内核版本2.6.32的TI Linux-Davinci-Staging。本文将从以下几个方面展开讨论: - **Linux内核管理的物理空间以及ARM架构下的4GB虚拟地址组织方式** -...
这份"操作系统习题与答案2021——2022"的资料,旨在帮助学习者深入理解操作系统的基本概念、原理及应用,为考试复习提供有效支持。以下是基于这个主题的详细知识点讲解: 1. **操作系统基础**: - **定义**:操作...
在虚拟存储管理中,页式管理系统是...总结来说,虚拟存储管理是操作系统中至关重要的部分,它通过页式管理系统和页面置换算法来实现内存的有效利用。理解这些概念和算法对于优化程序性能和系统资源管理具有重要意义。