操做系统核心原理-5.内存管理(上):基本内存管理

  操做系统的两个角色分别是魔术师和管理者,在管理者这个角色中,除了CPU以外,内存是操做系统要管理的另一个重要资源。内存管理须要达到两个目标:一是地址保护,即一个程序不能访问另外一个程序的地址空间。二是地址独立,即程序发出的地址应该与物理主存地址无关。这两个目标就是衡量一个内存管理系统是否完善的标准,它是全部内存管理系统必须提供的基本抽象。程序员

1、内存管理二三事

1.1 内存管理的目标

  (1)地址保护:一个程序不能访问另外一个程序地址空间。编程

  (2)地址独立:程序发出的地址应该与物理主存地址无关。小程序

  这两个目标是衡量一个内存管理系统是否完善的标准,它是全部内存管理系统必须提供的基本抽象。 函数

1.2 虚拟内存的概念

  虚拟内存的中心思想是将物理主存扩大到便宜、大容量的磁盘上,即将磁盘空间看作主存空间的一部分。能够理解为是将书桌上的比较老的文件先暂时收到抽屉里,用空出来的地方来摊开新的文件。在计算机中,体如今在内存容量不足时将不常常访问的内存空间中的数据写入硬盘,以增长“帐面上”可用内存容量的手段(想一想咱们的内存和硬盘容量对比就知道了)。spa

desk

  可是,若是在书桌和抽屉之间频繁进行文件的交换,工做效率确定会降低。若是每次要看一份文件都要先收拾书桌再到抽屉里面拿的话,那工做根本就没法进行了。操作系统

  虚拟内存的优势在于除了让程序员感受到内存容量大大增长以外,还让程序员感受到内存速度也增快了。翻译

  虚拟内存也有一样的缺点:硬盘的容量比内存大,但也只是相对的,速度却很是缓慢,若是和硬盘之间的数据交换过于频繁,处理速度就会降低,表面上看起来就像卡住了同样,这种现象称为抖动(Thrushing)。相信不少人都有过计算机中止响应的经历,而形成死机的主要缘由之一就是抖动。blog

2、基本内存管理

2.1 单道编程的内存管理

  在单道编程环境下,整个内存里面只有两个程序:一个是用户程序,另外一个是操做系统。递归

  因为只有一个用户程序,而操做系统所占用的内存空间是恒定的,因此咱们能够将用户程序老是加载到同一个内存地址上,即用户程序永远从同一个地方开始执行队列

  这样,用户程序里面的地址均可以事先计算出来,即在程序运行以前就计算出全部的物理地址。这种在运行前即将物理地址计算好的方式叫作静态地址翻译。下面看看此方式如何达到两个目标。

  (1)地址独立:用户在编写程序时无需考虑具体的物理内存,用户程序始终都被加载到同一个物理地址上。

  (2)地址保护:整个系统里面只有一个用户程序,所以,固定地址的内存管理由于只运行一个用户程序而达到地址保护。

2.2 多道编程的内存管理

  在多道编程环境下,没法将程序老是加到固定的内存地址上,也就是没法使用静态地址翻译。所以,必须在程序加载完毕以后才能计算物理地址,也就是在程序运行时进行地址翻译,这种翻译称为动态地址翻译

  多道编程环境下的内管管理策略有两种:

  (1)固定分区

  顾名思义,固定分区管理就是讲内存分为固定的几个区域,每一个区域大小固定。最下面的分区为OS占用,其余分区由用户程序使用。分区大小一般各不相同,当须要加载程序时,选择一个当前闲置且容量足够大的分区进行加载,以下图所示,这是一种共享队列的固定分区(多个用户程序排在一个共同的队列里面等待分区):

  因为程序大小和分区大小不必定匹配,有可能造成一个小程序占用一个大分区的状况,从而形成内存里虽然有小分区闲置但没法加载大程序的状况。这时,咱们就想到也许能够采用多个队列,给每一个分区一个队列,程序按照大小排在相应的队列里,以下图所示,这时一种分开队列的固定分区:

  上图这种方式也有缺点:若是还有空闲分区,但等待的程序不在该分区的等待队列上,就将形成有空间而不能运行程序的尴尬。

  (2)非固定分区

  非固定分区的思想在于除了划分给OS的空间以外,其他的内存空间是做为一个总体存在的。当一个程序须要占用内存空间时,就在该片空间里面分出一个大小刚刚知足程序所需的空间。再来一个程序时,则在剩下的空间里再这样分出一块来。在这种模式下,一个程序能够加载到任何地方,也能够和物理内存同样大。

  例如,一开始内存中只有OS,这时候进程A来了,因而分出一片与进程A大小同样的内存空间;随后,进程B来了,因而在进程A之上分出一片给进程B;而后进程C来了,就在进程B上面再分出一片给C。如此,进程A、B和C的起始地址都不是固定的,以下图所示:

  仔细一看,这种方式存在一个重大问题:每一个程序像叠罗汉同样累计,若是程序B在成型过程当中须要更多空间怎么办?(例如在实际程序中,不少递归嵌套函数调用的时候回形成栈空间的增加)所以,咱们能够想到能够再一开始的时候给程序分配空间时就分配足够大的空间,留有一片闲置空间供程序增加使用,以下图所示:

  不过,OS怎么知道应该分配多少空间给一个程序呢?分配多了,就是浪费;而分配少了,则可能形成程序没法继续执行。

  所以,能够在空间不够时,给程序换一个空间,这种方式将程序倒到磁盘上,再加载到内存中,被称为交换swap)。可是,若是在交换模式下程序的增加超过了物理内存,就不能再交换了。此时,能够将程序按照功能分红一段一段功能相对完整的单元,一个单元执行完成后再执行下一个单元,这就是重叠overlay)。

  可是,交换内存管理这种方式存在两个重要问题:

  (1)空间浪费:随着程序在内存与磁盘间的交换,内存将变得愈来愈碎片化,即内存将被不一样程序分割成尺寸大小没法使用的小片空间。

  (2)程序大小受限:这有两层意思,一是指空间增加效率低下(因为磁盘操做耗时,交换出去再找一片更大的空间来增加程序空间的作法效率很是低),二是空间增加存在天花板限制(单一程序不能超过物理内存空间)。

2.3 闲置空间管理

  在管理内存的时候,OS须要知道内存空间有多少空闲?这就必须跟踪内存的使用,跟踪的办法有两种:

  (1)给每一个分配单元赋予一个字位,用来记录该分配单元是否闲置。例如,字位取值为0表示单元闲置,取值为1则表示已被占用,这种表示方法就是位图表示法,以下图所示:

  (2)将分配单元按照是否闲置连接起来,这种方法称为链表表示法。如上图所示的的位图所表示的内存分配状态,使用链表来表示的话则会以下图所示:

  在链表表示下,寻找一个给定大小的闲置空间意味着找到一个类型为H的链表项,其大小大于或等于给定的目标值。不过,扫描链表速度一般较慢。

参考资料

邹恒明,《操做系统之哲学原理》,机械工业出版社

 

相关文章
相关标签/搜索