赞
踩
在单道程序设计中(即同时只允许一个进程在处理器中执行),内存被分为两个部分,一部分供操作系统使用,一部分供当前执行的用户程序使用。
而在多到程序设计中,CPU采用某些调度方式允许多个进程在一定意义上同时执行(当然在实际的围观角度来看并不是同时执行),因此用户程序使用的内存区域需要被进一步细分管理,从而满足多个进程的存放要求。这便叫内存管理。
主要包括以下几点:
内存重定位的需求来源于多道程序设计系统。
在这种设计方式下,可用的内存空间通常被多个进程共享使用,然而在一般情况下,程序员不能提前知道在某个程序运行期间有哪些其他程序驻留在内存中。
并且也希望通过就绪进程池将活跃的进程换入/换出内存,此时就需考虑该程序在下次换入内存时应该换到内存的哪块区域的问题:是否必须换入到之前的区域?如果是这样就十分地不灵活,因此有了一个需求:内存重定位。
内存重定位表示在进程换出换入后,允许通过一定的方式重定位到不同的内存区域的技术。
那么这种重定位技术如何实现的呢?
(待续)
每个进程都需要收到系统的保护,以避免其他进程对某个进程的内存进行非法访问。
由于程序在内存中的地址是不可预测的,因此在编译时不能通过检查绝对地址来确定是否符合安全要求,而只能在进程的运行过程中进行检查进程产生的所有内存访问,以确保该进程的访问是合理的。
内存保护不能通过操作系统以软件方式实现,只能通过处理器以硬件方式来实现。
操作系统无法预测程序可能产生的所有内存访问,即使可以预测,提前检查该进程的所有可能产生的内存访问也是一个极大耗费资源的操作。这种操作是不被允许的。
在访存指令执行时,通过处理器以硬件的方式来判断该内存访问(数据访问或分支跳转)是否合法。
处理器如何以硬件的方式来判断呢?
举一个例子:假如有大量进程执行同一个程序,有两种方案,一种是每个进程都有单独的该程序的副本,第二种方案是允许每个进程访问该程序的同一个副本。
显然第二种方式更加高效,灵活。
允许多个进程访问内存中的同一个区域。即操作系统需要能够控制对内存共享区域的访问,允许合法的访问而不损坏基本的保护。
虽然计算机系统中的内存/辅存结构一般被构造成线性地址空间,但是不符合构造程序的方式:大多程序是以模块化的方式构造的。
a)可以独立编写和编译模块,而将模块间的调用交给系统;
b)可以通过适当地引入开销,来实现位不同的模块设置不同的保护级别(只读/可执行/等)的效果;
c)可以引入某种机制,使得模块可以被多个进程共享访问。
分段。
计算机存储至少分为内存/外存两种方式。此处主要需要考虑的点就是内存与外存之间的信息流的组织。
对于程序员来说,他们不知道可供程序和数据使用的内存是否够用。若是如此的话,程序员需要自己通过覆盖(Overlaying)技术组织程序和数据,从而允许多个模块被分配到内存的同一块区域,然后自己实现内存/外存换入换出的管理。
毫无疑问,这是一个公共的需求,不应该让程序员去每次实现这种需求,而是应该让操作系统去实现。这也是内存管理的本质。
程序在换入换出时,不应该只允许起换入到之前相同的内存地址,而是应该更加灵活地分配。在这种需求下,就需要一种技术来进行程序的重定位到不同的内存区域,并且能够允许新的内存区域的程序可以被找到。
这就需要一种寻址技术来保证。
见上文,独立化模块的优势
简单来讲就是为了进行资源共享。若多个进程都需要某份资源,那么可以每个进程都拥有一份该资源的拷贝,这样就会每个进程都有一份内存占用,也可以所有内存都共同拥有该资源的一份拷贝,这样就可以减少内存占用。
当然这样需要操作系统对其内存访问的安全性进行保障。
在固定分区方案中,由于每个分区的大小都相等,十分不灵活,可能有以下几种情况:
a)程序太大以至于不能放到一个分区中。此时程序员需要使用覆盖技术来设计程序,从而允许在任何时候只需要将程序的一部分载入内存就可以使得程序正常运行。当需要的程序不在内存中时,用户程序必须覆盖程序所在分区的所有程序和数据,将该模块加载到分区中;
b)内存利用率低。当一个程序非常小的时候,也会占用一个分区,这样便导致了内部碎片(Internal Fragmentation)。
这两个劣势可以通过使用大小不等的分区来解决。但这也不是最好的解决方案。
使用大小不等的分区时,对于一个待加载的程序,可以采用两种不同的方式将其放到恰当的内存区域:
a)每个大小的内存区域都各自使用一个调度队列来管理,用来接收不同大小内存需求的进程,然后将其放入相应的分区中;
这种方式的好处在于,始终都能够将所有进程加载到能够容纳该进程的最小分区中,从而使内部碎片最少。
b)使用一个调度队列来存放所有需要的进程,然后按需将其放到不同的内存分区中。
内部与外部的定义是依据浪费的内存区域相对于可用区域的相对位置来说的。
是指在固定分区方式(无论是大小相等的分区还是大小不等的分区)下,由于分区是被固定的,加载进程的时候很少能够有刚刚好的情况,总会或多或少有浪费的情况,此处浪费的部分分区就被称为产生内部碎片。
是指在动态分区方式下,由于进程频繁地加载和退出,在之前加载在内存中间区域的进程被新的进程取代,若新的进程占用内存较小,就会在各个可用动态分区之间产生难以被其他进程使用的小碎片,此处浪费的部分分区被称为产生外部碎片。
外部碎片可以通过压缩 来解决,但会浪费处理器时间,而且需要内存动态重定位的支持,即需要将一个进程从一个内存区域移动到另一个内存区域,而不能影响其可用性。
逻辑地址(Logical Address):与当前数据在内存中的分配地址无关的访问地址,是个简单的线性地址,在执行内存访问之前需要转换成物理地址。
物理地址(Physical Address):也被称为绝对地址,是数据在内存中的实际地址。
页(Page)的产生是基于内存分区方案无法完美解决碎片问题的前提。
页框是内存的固定分割,使用绝对地址来编码,相当于将物理内存进行直接分割,可以直接定位访问。
页被分配用于保存进程数据,每个页对应于一个页框,相当于一个逻辑地址对应于一个物理地址,在分页机制下,逻辑地址由页号和偏移量组成,物理地址由页框号和偏移量组成,其对应关系使用**页表(Page Table)**来实现。
此时通过逻辑地址的使用可以允许操作系统在没有足够多未被使用的连续的内存页的情况下,允许操作系统加载程序。
即对于一个进程来说,只需通过逻辑地址来进行管理,而无需关心其保存在内存的什么地方,可以是不连续的,只需通过逻辑地址转换为物理地址进行访问即可。
考虑一个基于分页技术的内存管理系统,物理内存的总容量大小为2GB,页大小为8KB,每个进程的逻辑地址空间不超过256MB。
问:1. 物理地址有多少位?
2.参与页面置换的有多少位?页框号有多少位?
3. 有多少个页框?
4. 描述逻辑地址的结构。
分析:
页的大小为8KB,即8192字节,使用14个二进制位来表示:
每个进程的逻辑地址空间不超过256MB,使用19个二进制位来表示:
一共需要 14 + 19 = 33 位来表示LBA。
n * m
即使用左14位表示页号,右19位来表示偏移。
LBA->PBA的转换流程如下所示:
最大页框号取决于最大物理内存。 因为每个页大小为8KB,最大物理内存为2GB,可以计算出最大的页框数目为2GB / 8KB = 262144 个,因此最大页框号为262143.
最大需要19位来表示。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。