精华内容
下载资源
问答
  • 操作系统内存管理

    千次阅读 2018-08-20 10:43:12
    虽然物理内存的增长现在达到了N个GB,但比物理内存增长还快的是程序,所以无论物理内存如何增长,都赶不上程序增长的速度,所以操作系统如何有效的管理内存便显得尤为重要。本文讲述操作系统对于内存管理的过去和...

    简介

        内存是计算机中最重要的资源之一,通常情况下,物理内存无法容纳下所有的进程。虽然物理内存的增长现在达到了N个GB,但比物理内存增长还快的是程序,所以无论物理内存如何增长,都赶不上程序增长的速度,所以操作系统如何有效的管理内存便显得尤为重要。本文讲述操作系统对于内存的管理的过去和现在,以及一些页替换的算法的介绍。

     

    对于进程的简单介绍

        在开始之前,首先从操作系统的角度简单介绍一下进程。进程是占有资源的最小单位,这个资源当然包括内存。在现代操作系统中,每个进程所能访问的内存是互相独立的(一些交换区除外)。而进程中的线程所以共享进程所分配的内存空间。

        在操作系统的角度来看,进程=程序+数据+PCB(进程控制块)。这个概念略微有点抽象,我通过一个类比来说吧:比如,你正在厨房做饭,你一边看着菜谱一边按照菜谱将原料做成菜,就在这时,你儿子进来告诉你他擦破了腿,此时你停下手中的工作,将菜谱反扣过来,然后找来急救书按照书中的内容给你儿子贴上创口贴,贴完后你继续回去打开菜谱,然后继续做饭。在这个过程中,你就好比CPU,菜谱就好比程序,而做菜的原料就好比数据。你按照程序指令加工数据,而急救工作好比一个更高优先级的进程,中断了你当前做饭的工作,然后你将菜谱反扣过来(保护现场),转而去处理高优先级的进程,处理完毕后你继续从刚才的页读菜谱(恢复现场),然后继续执行做菜这个进程。

        在简单介绍完进程的概念后,我们来转入内存。

     

    没有内存抽象的年代

        在早些的操作系统中,并没有引入内存抽象的概念。程序直接访问和操作的都是物理内存。比如当执行如下指令时:

    mov reg1,1000

     

        这条指令会毫无想象力的将物理地址1000中的内容赋值给寄存器。不难想象,这种内存操作方式使得操作系统中存在多进程变得完全不可能,比如MS-DOS,你必须执行完一条指令后才能接着执行下一条。如果是多进程的话,由于直接操作物理内存地址,当一个进程给内存地址1000赋值后,另一个进程也同样给内存地址赋值,那么第二个进程对内存的赋值会覆盖第一个进程所赋的值,这回造成两条进程同时崩溃。

        没有内存抽象对于内存的管理通常非常简单,除去操作系统所用的内存之外,全部给用户程序使用。或是在内存中多留一片区域给驱动程序使用,如图1所示。

        1

        图1.没有内存抽象时,对内存的使用

      

        第一种情况操作系统存于RAM中,放在内存的低地址,第二种情况操作系统存在于ROM中,存在内存的高地址,一般老式的手机操作系统是这么设计的。

        如果这种情况下,想要操作系统可以执行多进程的话,唯一的解决方案就是和硬盘搞交换,当一个进程执行到一定程度时,整个存入硬盘,转而执行其它进程,到需要执行这个进程时,再从硬盘中取回内存,只要同一时间内存中只有一个进程就行,这也就是所谓的交换(Swapping)技术。但这种技术由于还是直接操作物理内存,依然有可能引起进程的崩溃。

        所以,通常来说,这种内存操作往往只存在于一些洗衣机,微波炉的芯片中,因为不可能有第二个进程去征用内存。

     

    内存抽象

        在现代的操作系统中,同一时间运行多个进程是再正常不过的了。为了解决直接操作内存带来的各种问题,引入的地址空间(Address Space),这允许每个进程拥有自己的地址。这还需要硬件上存在两个寄存器,基址寄存器(base register)和界址寄存器(limit register),第一个寄存器保存进程的开始地址,第二个寄存器保存上界,防止内存溢出。在内存抽象的情况下,当执行

    mov reg1,20

     

        这时,实际操作的物理地址并不是20,而是根据基址和偏移量算出实际的物理地址进程操作,此时操作的实际地址可能是:

    mov reg1,16245

     

        在这种情况下,任何操作虚拟地址的操作都会被转换为操作物理地址。而每一个进程所拥有的内存地址是完全不同的,因此也使得多进程成为可能。

        但此时还有一个问题,通常来说,内存大小不可能容纳下所有并发执行的进程。因此,交换(Swapping)技术应运而生。这个交换和前面所讲的交换大同小异,只是现在讲的交换在多进程条件下。交换的基本思想是,将闲置的进程交换出内存,暂存在硬盘中,待执行时再交换回内存,比如下面一个例子,当程序一开始时,只有进程A,逐渐有了进程B和C,此时来了进程D,但内存中没有足够的空间给进程D,因此将进程B交换出内存,分给进程D。如图2所示。

        2

        图2.交换技术

     

        通过图2,我们还发现一个问题,进程D和C之间的空间由于太小无法另任何进程使用,这也就是所谓的外部碎片。一种方法是通过紧凑技术(Memory Compaction)解决,通过移动进程在内存中的地址,使得这些外部碎片空间被填满。还有一些讨巧的方法,比如内存整理软件,原理是申请一块超大的内存,将所有进程置换出内存,然后再释放这块内存,从而使得从新加载进程,使得外部碎片被消除。这也是为什么运行完内存整理会狂读硬盘的原因。另外,使用紧凑技术会非常消耗CPU资源,一个2G的CPU没10ns可以处理4byte,因此多一个2G的内存进行一次紧凑可能需要好几秒的CPU时间。

        上面的理论都是基于进程所占的内存空间是固定的这个假设,但实际情况下,进程往往会动态增长,因此创建进程时分配的内存就是个问题了,如果分配多了,会产生内部碎片,浪费了内存,而分配少了会造成内存溢出。一个解决方法是在进程创建的时候,比进程实际需要的多分配一点内存空间用于进程的增长。一种是直接多分配一点内存空间用于进程在内存中的增长,另一种是将增长区分为数据段和栈(用于存放返回地址和局部变量),如图3所示。

        3

        图3.创建进程时预留空间用于增长

     

        当预留的空间不够满足增长时,操作系统首先会看相邻的内存是否空闲,如果空闲则自动分配,如果不空闲,就将整个进程移到足够容纳增长的空间内存中,如果不存在这样的内存空间,则会将闲置的进程置换出去。

         当允许进程动态增长时,操作系统必须对内存进行更有效的管理,操作系统使用如下两种方法之一来得知内存的使用情况,分别为1)位图(bitmap) 2)链表

         使用位图,将内存划为多个大小相等的块,比如一个32K的内存1K一块可以划为32块,则需要32位(4字节)来表示其使用情况,使用位图将已经使用的块标为1,位使用的标为0.而使用链表,则将内存按使用或未使用分为多个段进行链接,这个概念如图4所示。

        4

         图4.位图和链表表示内存的使用情况

     

         使用链表中的P表示进程,从0-2是进程,H表示空闲,从3-4表示是空闲。

         使用位图表示内存简单明了,但一个问题是当分配内存时必须在内存中搜索大量的连续0的空间,这是十分消耗资源的操作。相比之下,使用链表进行此操作将会更胜一筹。还有一些操作系统会使用双向链表,因为当进程销毁时,邻接的往往是空内存或是另外的进程。使用双向链表使得链表之间的融合变得更加容易。

        还有,当利用链表管理内存的情况下,创建进程时分配什么样的空闲空间也是个问题。通常情况下有如下几种算法来对进程创建时的空间进行分配。

    •      临近适应算法(Next fit)---从当前位置开始,搜索第一个能满足进程要求的内存空间
    •      最佳适应算法(Best fit)---搜索整个链表,找到能满足进程要求最小内存的内存空间
    •      最大适应算法(Wrost fit)---找到当前内存中最大的空闲空间
    •      首次适应算法(First fit) ---从链表的第一个开始,找到第一个能满足进程要求的内存空间

     

    虚拟内存(Virtual Memory)

        虚拟内存是现代操作系统普遍使用的一种技术。前面所讲的抽象满足了多进程的要求,但很多情况下,现有内存无法满足仅仅一个大进程的内存要求(比如很多游戏,都是10G+的级别)。在早期的操作系统曾使用覆盖(overlays)来解决这个问题,将一个程序分为多个块,基本思想是先将块0加入内存,块0执行完后,将块1加入内存。依次往复,这个解决方案最大的问题是需要程序员去程序进行分块,这是一个费时费力让人痛苦不堪的过程。后来这个解决方案的修正版就是虚拟内存。

        虚拟内存的基本思想是,每个进程有用独立的逻辑地址空间,内存被分为大小相等的多个块,称为页(Page).每个页都是一段连续的地址。对于进程来看,逻辑上貌似有很多内存空间,其中一部分对应物理内存上的一块(称为页框,通常页和页框大小相等),还有一些没加载在内存中的对应在硬盘上,如图5所示。

        5

        图5.虚拟内存和物理内存以及磁盘的映射关系

     

        由图5可以看出,虚拟内存实际上可以比物理内存大。当访问虚拟内存时,会访问MMU(内存管理单元)去匹配对应的物理地址(比如图5的0,1,2),而如果虚拟内存的页并不存在于物理内存中(如图5的3,4),会产生缺页中断,从磁盘中取得缺的页放入内存,如果内存已满,还会根据某种算法将磁盘中的页换出。

        而虚拟内存和物理内存的匹配是通过页表实现,页表存在MMU中,页表中每个项通常为32位,既4byte,除了存储虚拟地址和页框地址之外,还会存储一些标志位,比如是否缺页,是否修改过,写保护等。可以把MMU想象成一个接收虚拟地址项返回物理地址的方法。

        因为页表中每个条目是4字节,现在的32位操作系统虚拟地址空间会是2的32次方,即使每页分为4K,也需要2的20次方*4字节=4M的空间,为每个进程建立一个4M的页表并不明智。因此在页表的概念上进行推广,产生二级页表,二级页表每个对应4M的虚拟地址,而一级页表去索引这些二级页表,因此32位的系统需要1024个二级页表,虽然页表条目没有减少,但内存中可以仅仅存放需要使用的二级页表和一级页表,大大减少了内存的使用。

     

    页面替换算法

        因为在计算机系统中,读取少量数据硬盘通常需要几毫秒,而内存中仅仅需要几纳秒。一条CPU指令也通常是几纳秒,如果在执行CPU指令时,产生几次缺页中断,那性能可想而知,因此尽量减少从硬盘的读取无疑是大大的提升了性能。而前面知道,物理内存是极其有限的,当虚拟内存所求的页不在物理内存中时,将需要将物理内存中的页替换出去,选择哪些页替换出去就显得尤为重要,如果算法不好将未来需要使用的页替换出去,则以后使用时还需要替换进来,这无疑是降低效率的,让我们来看几种页面替换算法。

       

    最佳置换算法(Optimal Page Replacement Algorithm)

         最佳置换算法是将未来最久不使用的页替换出去,这听起来很简单,但是无法实现。但是这种算法可以作为衡量其它算法的基准。

     

    最近不常使用算法(Not Recently Used Replacement Algorithm)

         这种算法给每个页一个标志位,R表示最近被访问过,M表示被修改过。定期对R进行清零。这个算法的思路是首先淘汰那些未被访问过R=0的页,其次是被访问过R=1,未被修改过M=0的页,最后是R=1,M=1的页。

     

    先进先出页面置换算法(First-In,First-Out Page Replacement Algorithm)

        这种算法的思想是淘汰在内存中最久的页,这种算法的性能接近于随机淘汰。并不好。

     

    改进型FIFO算法(Second Chance Page Replacement Algorithm)

        这种算法是在FIFO的基础上,为了避免置换出经常使用的页,增加一个标志位R,如果最近使用过将R置1,当页将会淘汰时,如果R为1,则不淘汰页,将R置0.而那些R=0的页将被淘汰时,直接淘汰。这种算法避免了经常被使用的页被淘汰。

     

    时钟替换算法(Clock Page Replacement Algorithm)

        虽然改进型FIFO算法避免置换出常用的页,但由于需要经常移动页,效率并不高。因此在改进型FIFO算法的基础上,将队列首位相连形成一个环路,当缺页中断产生时,从当前位置开始找R=0的页,而所经过的R=1的页被置0,并不需要移动页。如图6所示。

        6

        图6.时钟置换算法

     

    最久未使用算法(LRU Page Replacement Algorithm)

        LRU算法的思路是淘汰最近最长未使用的页。这种算法性能比较好,但实现起来比较困难。

     

    下面表是上面几种算法的简单比较:

    算法 描述
    最佳置换算法 无法实现,最为测试基准使用
    最近不常使用算法 和LRU性能差不多
    先进先出算法 有可能会置换出经常使用的页
    改进型先进先出算法 和先进先出相比有很大提升
    最久未使用算法 性能非常好,但实现起来比较困难
    时钟置换算法 非常实用的算法

     

        上面几种算法或多或少有一些局部性原理的思想。局部性原理分为时间和空间上的局部性

        1.时间上,最近被访问的页在不久的将来还会被访问。

        2.空间上,内存中被访问的页周围的页也很可能被访问。

    展开全文
  • 内存与操作系统内存管理

    千次阅读 2021-02-28 15:10:12
    内存与操作系统内存管理 文章目录内存与操作系统内存管理一、内存的基础知识二、内存管理2.1 内存空间扩充2.2 内存空间的分配与回收 一、内存的基础知识   内存是用于存放数据的硬件,程序执行前需要将数据放入...

    内存与操作系统内存管理



    Java、大数据开发学习要点(持续更新中…)


    一、内存的基础知识

      内存是用于存放数据的硬件,程序执行前需要将数据放入内存中才能被CPU处理。内存通过对内部的存储单元编址来解决并发执行下各个程序的数据区分,根据计算机字长的不同,存储单元大小不同(如64位计算机每个字大小为64位,8个字节)。
      内存存放的相对寻址:编译语言编译后的指令寻址,是通过相对地址实现的,实际存入内存时再根据进程在内存中的起始地值得到绝对地址。编译生成的机器语言中的地址实际都是逻辑地址,再通过链接(形成完整逻辑地址)后,通过装入模块装入内存运行,这时将逻辑地址转换成物理地址(主要使用动态重定位装入方法:CPU内有重定位寄存器保存了程序存放内存的起始位置,结合逻辑地址可以实现动态重定位)。

    二、内存管理

      操作系统是系统资源的管理者,也需要对内存进行管理。操作系统需要负责以下事情:

    1. 提供某种技术从逻辑上对内存空间进行扩充
    2. 内存空间的分配与回收
    3. 提供地址转换功能,负责程序从逻辑地址到物理地址的转换(动态重定位,依赖于重定位寄存器)
    4. 提供内存保护功能,保证各个进程在各自存储空间内运行,互不干扰。

    2.1 内存空间扩充

      操作系统对内存空间的扩充主要有覆盖技术、交换技术和虚拟存储技术(后面详细介绍):

    • 覆盖技术:用于早期操作系统中。
    • 交换技术:实际就是进程调度中的内存调度,进程在内存和磁盘间动态调度(进程未结束前内存中始终保留PCB信息)。进程从内存中被换出是保存在磁盘的对换区中(这个区域I/O速度比文件区快,详细在文件部分讲解)。

    2.2 内存空间的分配与回收**

      内存空间分配分为连续分配管理方式和非连续分配管理方式:

    (1)连续分配管理方式中又分为单一连续分配、固定分区分配和动态分区分配

    • 单一连续分配,只适用于单任务操作系统。
    • 固定分区分配,将内存中除了系统区外的用户空间分为固定大小或大小不等的分区,并建立分区说明表的数据结构(数组或链表)记录每个分区大小、起始地址、状态等信息,缺点在于用户程序过大需要覆盖技术支持,且会产生内部碎片。
    • 动态分区分配,在进程装入内存时,动态地建立分区。操作系统使用空闲分区表或空闲分区链来记录内存使用情况(分区号、分区大小、起始地址等)。
      常用记录内存使用情况的数据结构
      而当新的进程要装入内存时,需要用动态分区分配算法来选择出一个合适的分区。

    (2)非连续分配管理方式为用户进程分配的可以是一些分散的内存空间,主要管理方式有分页存储管理分段存储管理段页式存储管理

    • 分页存储管理:将内存空间分为大小相等的小分区,每个分区称为页框,编号从0开始。相应地,将用户进程的地址空间也分为 与页框大小相等 的一个个区域,每个部分称为,编号同样从0开始。(注:进程的最后一个页可能没有一个页框那么大,因此页框不能过大,否则可能产生过大的内部碎片)
        那么分页存储是离散存储的,如何实现逻辑地址到物理地址的转换?
        将动态重定位的思想使用到分页存储中,首先计算逻辑地址对应的页号(逻辑地址/页面大小)和页内偏移量(逻辑地址%页面大小),得到该页号在内存中存放的起始地址,由此物理地址=页面地址+页内偏移量。而要知道进程的每个页在内存中存放的位置,操作系统需要为每个进程建立一张页表
      分页基本地址变化过程
    • 分段存储管理按照程序自身逻辑关系划分为若干个段,每个段有一个段名,每段从0开始编址。每个段在内存中占据连续空间,但各个段之间可以不相邻。与分页存储类似,操作系统在分段存储时为每个进程建立一张段表来保存各个段离散装入内存对应的段长、基址(与分页相似,段表项长度相同,可以通过段表计算段号,所以段号是隐含的不占存储空间)等信息。分段存储管理逻辑地址到物理地址的转换如下图:
      分段基本地址变化过程
      可以看出分段存储中由于每个段的长度都不同,因此对比分页存储多了段内地址越界检查。
    • 分段与分页的对比
    1. 信息的物理单元对用户不可见,信息的逻辑单元对用户可见。
    2. 大小固定且由系统决定长度不固定且决定于用户编写的程序
    3. 分页用户进程地址是一维的(只需要一个记忆符),分段用户进程地址是二维的(需要给出段名和段内地址)。
    4. 分段更容易实现信息的共享和保护(只能共享不属于临界资源的代码),当需要让内存中的某个片段共享给多个进程,只需要将各个进程的段表指向同一个段即可。
    • 加快分页过程
    1. 如何提高逻辑地址和物理地址的映射速度?(快表)
        系统一旦访问了某一个页,就会在一段时间内稳定工作在这个页上。所以为了提高访问页表的速度,计算机配备了一组能容纳部分页表的硬件寄存器。当系统再次需要将地址转换时,先访问这组硬件寄存器(即,快表)。
    2. 页表过大怎么解决?
        页表存在的问题是,页表必须连续存放在多个连续的页框中,页表过大时离散存储失去了其本质意义,所以可以再建一级索引(二级页表)来让原页表连续页表项分组离散存储。

    参考:《王道考研操作系统》
    地址:https://www.bilibili.com/video/BV1YE411D7nH

    展开全文
  • 操作系统内存管理总结 关于内存管理这一块的学习进行自己简单的总结,如有错误,请指出交流,一起学习进步… 我抽离出几个概念来总结。 虚拟内存 虚拟内存其实就是一种操作系统的内存管理机制,使得看起来有比真正...

    操作系统内存管理总结

    关于内存管理这一块的学习进行自己简单的总结,如有错误,请指出交流,一起学习进步…
    我抽离出几个概念来总结。

    虚拟内存
    虚拟内存其实就是一种操作系统的内存管理机制,使得看起来有比真正拥有的内存更大的空间,其一部分映射到物理内存,一部分对应在磁盘上。

    虚拟内存允许执行进程不必完全在内存中。虚拟内存的基本思想是:每个进程拥有独立的地址空间,这个空间被分为大小相等的多个块,称为页(Page),每个页都是一段连续的地址。这些页被映射到物理内存,但并不是所有的页都必须在内存中才能运行程序。当程序引用到一部分在物理内存中的地址空间时,由硬件立刻进行必要的映射;当程序引用到一部分不在物理内存中的地址空间时,由操作系统负责将缺失的部分装入物理内存并重新执行失败的命令。这样,对于进程而言,逻辑上似乎有很大的内存空间,实际上其中一部分对应物理内存上的一块(称为帧,通常页和帧大小相等),还有一些没加载在内存中的对应在硬盘上,如下图所示。

    在这里插入图片描述
    访问虚拟内存
    访问虚拟内存时,如果访问到的已经映射在物理内存上则直接访问物理内存,如果发现访问的虚拟内存并不在物理内存上,会产生缺页中断,从磁盘中取得缺的页放入内存,如果内存已满,还会根据某种算法将磁盘中的页换出,这里有几种置换算法,置换出来的数据储存在磁盘(Linux的swap区、Windows的C盘)

    • 先进先出算法,可能会置换出常用的页面
    • LRU,难实现
    • OPT,实现不了
    • 时钟,插入时设为1、使用时设为1;置换时发现为1的设为0,发现0的直接置换

    分段和分页

    • 分段:
      这是为了满足用户要求而形成的一种储存管理方式。它把用户程序的地址空间分为若干个大小不同的段,每段可定义一组相对完整的信息。在储存器分配时,以段为单位,这些段在内存中可以不相邻接,所以也同样实现了离散分配。
    • 分页:
      系统管理需要,在该方式中,将用户程序地址空间分为若干固定大小的区域,称为“页”或“页面”。典型的页面大小为1KB。相应的,也将内存空间分为若干个物理块或页框(frame),页和块的大小相同。这样可将用户程序的任一页放入任一物理块中,实现了离散分配。

    分段分页区别
    目的不同:分页是由于系统管理的需要而不是用户的需要,它是信息的物理单位;分段的目的是为了能更好地满足用户的需要,它是信息的逻辑单位,它含有一组其意义相对完整的信息;
    大小不同:页的大小固定且由系统决定,而段的长度却不固定,由其所完成的功能决定;
    地址空间不同: 段向用户提供二维地址空间;页向用户提供的是一维地址空间;
    信息共享:段是信息的逻辑单位,便于存储保护和信息的共享,页的保护和共享受到限制;
    内存碎片:页式存储管理的优点是没有外碎片(因为页的大小固定),但会产生内碎片(一个页可能填充不满);而段式管理的优点是没有内碎片(因为段大小可变,改变段大小来消除内碎片)。但段换入换出时,会产生外碎片(比如4k的段换5k的段,会产生1k的外碎片)。

    参考文章:
    https://zhuanlan.zhihu.com/p/19965403
    https://www.jianshu.com/p/76db050b808c

    展开全文
  • 操作系统内存管理(思维导图详解)

    万次阅读 多人点赞 2010-07-05 11:26:00
    在介绍内存管理的细节前,先要了解一下分层存储器体系: 大部分的计算机都有一个存储器层次结构,即少量的非常快速、昂贵、易变的高速缓存(cache);若干兆字节的中等速度、中等价格、易变的主存储器(RAM);...

    操作系统内存管理:总的来说,操作系统内存管理包括物理内存管理和虚拟内存管理。

    物理内存管理:

           包括程序装入等概念、交换技术、连续分配管理方式和非连续分配管理方式(分页、分段、段页式)。

    虚拟内存管理:
          虚拟内存管理包括虚拟内存概念、请求分页管理方式、页面置换算法、页面分配策略、工作集和抖动。

          这个系列主要使用linux内存管理来具体说明:linux内存管理

     

    一、 计算机的存储体系


    内存是计算机很重要的一个资源,因为程序只有被加载到内存中才可以运行;此外,CPU所需要的指令与数据也都是来自内存的。可以说,内存是影响计算机性能的一个很重要的因素。

    分层存储器体系

    在介绍内存管理的细节前,先要了解一下分层存储器体系:

    大部分的计算机都有一个存储器层次结构,即少量的非常快速、昂贵、易变的高速缓存(cache);若干兆字节的中等速度、中等价格、易变的主存储器(RAM);数百兆或数千兆的低速、廉价、不易变的磁盘。这些资源的合理使用与否直接关系着系统的效率。

    CPU缓存(Cache Memory):是位于CPU与内存之间的临时存储器,它的容量比内存小的多但是交换速度却比内存要快得多。缓存的出现主要是为了解决CPU运算速度与内存 读写速度不匹配的矛盾,因为CPU运算速度要比内存读写速度快很多,这样会使CPU花费很长时间等待数据到来或把数据写入内存。

    计算机是一种数据处理设备,它由CPU和内存以及外部设备组成。CPU负责数据处理,内存负责存储,外部设备负责数据的输入和输出,它们之间通过总线连接在一起。CPU内部主要由控制器、运算器和寄存器组成。控制器负责指令的读取和调度,运算器负责指令的运算执行,寄存器负责数据的存储,它们之间通过CPU内的总线连接在一起。每个外部设备(例如:显示器、硬盘、键盘、鼠标、网卡等等)则是由外设控制器、I/O端口、和输入输出硬件组成。外设控制器负责设备的控制和操作,I/O端口负责数据的临时存储,输入输出硬件则负责具体的输入输出,它们间也通过外部设备内的总线连接在一起。

    上面计算机系统结构图中我们可以看出硬件系统的这种组件化的设计思路总是贯彻到各个环节。

     在这套设计思想(冯.诺依曼体系架构)里面:  总是有一部分负责控制、一部分负责执行、一部分则负责存储,它之间进行交互以及接口通信则总是通过总线来完成。这种设计思路一样的可以应用在我们的软件设计体系里面:组件和组件之间通信通过事件的方式来进行解耦处理,而一个组件内部同样也需要明确好各个部分的职责(一部分负责调度控制、一部分负责执行实现、一部分负责数据存储)。

     

    计算存储的层次结构

    当前技术没有能够提供这样的存储器,因此大部分的计算机都有一个存储器层次结构:

    高速缓存(cache): 少量的非常快速、昂贵、易变的高速缓存(cache);

    主存储器(RAM): 若干兆字节的中等速度、中等价格、易变的主存储器(RAM);

    磁盘:  数百兆或数千兆的低速、廉价、不易变的磁盘。

    这些资源的合理使用与否直接关系着系统的效率。

     

    二、内存使用演化


    1、没有内存抽象的年代

    在早些的操作系统中,并没有引入内存抽象的概念。程序直接访问和操作的都是物理内存,内存的管理也非常简单,除去操作系统所用的内存之外,全部给用户程序使用,想怎么折腾都行,只要别超出最大的容量。比如当执行如下指令时:mov reg1,1000

    1、无内存抽象存在的问题:

    这条指令会毫无想象力的将物理地址1000中的内容赋值给寄存器。不难想象,这种内存操作方式使得操作系统中存在多进程变得完全不可能,比如MS-DOS,你必须执行完一条指令后才能接着执行下一条。如果是多进程的话,由于直接操作物理内存地址,当一个进程给内存地址1000赋值后,另一个进程也同样给内存地址赋值,那么第二个进程对内存的赋值会覆盖第一个进程所赋的值,这回造成两条进程同时崩溃。

    带来两个问题:

    1. 用户程序可以访问任意内存,容易破坏操作系统,造成崩溃

    2. 同时运行多个程序特别困难

    随着计算机技术发展,要求操作系统支持多进程的需求,所谓多进程,并不需要同时运行这些进程,只要它们都处于 ready 状态,操作系统快速地在它们之间切换,就能达到同时运行的假象。每个进程都需要内存,Context Switch 时,之前内存里的内容怎么办?简单粗暴的方式就是先 dump 到磁盘上,然后再从磁盘上 restore 之前 dump 的内容(如果有的话),但效果并不好,太慢了!

    2、内存抽象:地址空间

    那怎么才能不慢呢?把进程对应的内存依旧留在物理内存中,需要的时候就切换到特定的区域。这就涉及到了内存的保护机制,毕竟进程之间可以随意读取、写入内容就乱套了,非常不安全。因此操作系统需要对物理内存做一层抽象,也就是「地址空间」(Address Space),一个进程的地址空间包含了该进程所有相关内存,比如 code / stack / heap。一个 16 KB 的地址空间可能长这样:

    当程序运行时,heap 和 stack 共用中间 free 的区域,当然这只是 OS 层面的抽象。比如下面这段代码:

    int x;
    
    x = x + 3; // this is the line of code we are interested in

    变成汇编指令后,大概是这样:

    128: movl 0x0(%ebx), %eax  ;load 0+ebx into eax
    132: addl $0x03, %eax ;add 3 to eax register
    135: movl %eax, 0x0(%ebx) ;store eax back to mem

    最前面的是 PC (Program Counter),用来表示当前 code 的索引,比如 CPU 执行到 128 时,进行了 Context Switch(上下文切换),那么在 Switch 回来后,还可以接着从 132 开始执行(当然需要先把 PC 存起来)。之后的就是汇编代码,告诉 CPU 该如何操作。

    从进程的角度看,内存可能是这样的:

    真实的物理内存可能是这样的:

    基址寄存器与界限寄存器可以简单的动态重定位:每个内存地址送到内存之前,都会自动加上基址寄存器的内容。

    从 32KB 处作为开始,48KB 作为结束。那 32 / 48 可不可以动态设置呢,只要在 CPU 上整两个寄存器,基址寄存器base 和 界限寄存器bounds 就可以了,base 指明从哪里开始,bounds 指定哪里是边界。 因此真实物理地址和虚拟地址之间的关系是:

    physical address = virtual address + base

    有时,CPU 上用来做内存地址翻译的也会被叫做「内存管理单元 MMU」(Memory Management Unit),随着功能越来越强大,MMU 也会变得越来越复杂。

    base and bounds 这种做法最大的问题在于空间浪费,Stack 和 Heap 中间有一块 free space,即使没有用,也被占着,那如何才能解放这块区域呢,进入虚拟内存。

     

    3、虚拟内存

    虚拟内存是现代操作系统普遍使用的一种技术。前面所讲的抽象满足了多进程的要求,但很多情况下,现有内存无法满足仅仅一个大进程的内存要求。物理内存不够用的情况下,如何解决呢?

     覆盖overlays:在早期的操作系统曾使用覆盖技术来解决这个问题,将一个程序分为多个块,基本思想是先将块0加入内存,块0执行完后,将块1加入内存。依次往复,这个解决方案最大的问题是需要程序员去程序进行分块,这是一个费时费力让人痛苦不堪的过程。后来这个解决方案的修正版就是虚拟内存。
    交换swapping:可以将暂时不能执行的程序(进程)送到外存中,从而获得空闲内存空间来装入新程序(进程),或读人保存在外存中而处于就绪状态的程序。

    虚拟内存:虚拟内存的基本思想是,每个进程有用独立的逻辑地址空间,内存被分为大小相等的多个块,称为(Page).每个页都是一段连续的地址。对于进程来看,逻辑上貌似有很多内存空间,其中一部分对应物理内存上的一块(称为页框,通常页和页框大小相等),还有一些没加载在内存中的对应在硬盘上。

     

    三. 物理内存:连续分配存储管理方式


          连续分配是指为一个用户程序分配连续的内存空间。连续分配有单一连续存储管理和分区式储管理两种方式。

    3.1 单一连续存储管理

         在这种管理方式中,内存被分为两个区域:系统区和用户区。应用程序装入到用户区,可使用用户区全部空间。其特点是,最简单,适用于单用户、单任务的操作系统。CP/M和 DOS 2.0以下就是采用此种方式。这种方式的最大优点就是易于管理。但也存在着一些问题和不足之处,例如对要求内存空间少的程序,造成内存浪费;程序全部装入,使得很少使用的程序部分也占用—定数量的内存。

    3.2 分区式存储管理

           为了支持多道程序系统和分时系统,支持多个程序并发执行,引入了分区式存储管理。分区式存储管理是把内存分为一些大小相等或不等的分区,操作系统占用其中一个分区,其余的分区由应用程序使用,每个应用程序占用一个或几个分区。分区式存储管理虽然可以支持并发,但难以进行内存分区的共享。

           分区式存储管理引人了两个新的问题:内碎片和外碎片

          内碎片是占用分区内未被利用的空间,外碎片是占用分区之间难以利用的空闲分区(通常是小空闲分区)。

           为实现分区式存储管理,操作系统应维护的数据结构为分区表或分区链表。表中各表项一般包括每个分区的起始地址、大小及状态(是否已分配)。

          分区式存储管理常采用的一项技术就是内存紧缩(compaction)。

    3.2.1 固定分区(nxedpartitioning)。

            固定式分区的特点是把内存划分为若干个固定大小的连续分区。分区大小可以相等:这种作法只适合于多个相同程序的并发执行(处理多个类型相同的对象)。分区大小也可以不等:有多个小分区、适量的中等分区以及少量的大分区。根据程序的大小,分配当前空闲的、适当大小的分区。

          优点:易于实现,开销小。

          缺点主要有两个:内碎片造成浪费;分区总数固定,限制了并发执行的程序数目。

    3.2.2动态分区(dynamic partitioning)。

            动态分区的特点是动态创建分区:在装入程序时按其初始要求分配,或在其执行过程中通过系统调用进行分配或改变分区大小。与固定分区相比较其优点是:没有内碎片。但它却引入了另一种碎片——外碎片。动态分区的分区分配就是寻找某个空闲分区,其大小需大于或等于程序的要求。若是大于要求,则将该分区分割成两个分区,其中一个分区为要求的大小并标记为“占用”,而另一个分区为余下部分并标记为“空闲”。分区分配的先后次序通常是从内存低端到高端。动态分区的分区释放过程中有一个要注意的问题是,将相邻的空闲分区合并成一个大的空闲分区。

    下面列出了几种常用的分区分配算法:

            最先适配法(nrst-fit):按分区在内存的先后次序从头查找,找到符合要求的第一个分区进行分配。该算法的分配和释放的时间性能较好,较大的空闲分区可以被保留在内存高端。但随着低端分区不断划分会产生较多小分区,每次分配时查找时间开销便会增大。

           下次适配法(循环首次适应算法 next fit):按分区在内存的先后次序,从上次分配的分区起查找(到最后{区时再从头开始},找到符合要求的第一个分区进行分配。该算法的分配和释放的时间性能较好,使空闲分区分布得更均匀,但较大空闲分区不易保留。

           最佳适配法(best-fit):按分区在内存的先后次序从头查找,找到其大小与要求相差最小的空闲分区进行分配。从个别来看,外碎片较小;但从整体来看,会形成较多外碎片优点是较大的空闲分区可以被保留。

           最坏适配法(worst- fit):按分区在内存的先后次序从头查找,找到最大的空闲分区进行分配。基本不留下小空闲分区,不易形成外碎片。但由于较大的空闲分区不被保留,当对内存需求较大的进程需要运行时,其要求不易被满足。

    3.3 伙伴系统

            固定分区和动态分区方式都有不足之处。固定分区方式限制了活动进程的数目,当进程大小与空闲分区大小不匹配时,内存空间利用率很低。动态分区方式算法复杂,回收空闲分区时需要进行分区合并等,系统开销较大。伙伴系统方式是对以上两种内存方式的一种折衷方案。
            伙伴系统规定,无论已分配分区或空闲分区,其大小均为 2 的 k 次幂,k 为整数, l≤k≤m,其中:

            2^1 表示分配的最小分区的大小,

            2^m 表示分配的最大分区的大小,

            通常 2^m是整个可分配内存的大小。
            假设系统的可利用空间容量为2^m个字, 则系统开始运行时, 整个内存区是一个大小为2^m的空闲分区。在系统运行过中, 由于不断的划分,可能会形成若干个不连续的空闲分区,将这些空闲分区根据分区的大小进行分类,对于每一类具有相同大小的所有空闲分区,单独设立一个空闲分区双向链表。这样,不同大小的空闲分区形成了k(0≤k≤m)个空闲分区链表。 

           分配步骤:

           当需要为进程分配一个长度为n 的存储空间时:

           首先计算一个i 值,使 2^(i-1) <n ≤ 2^i,

           然后在空闲分区大小为2^i的空闲分区链表中查找。

           若找到,即把该空闲分区分配给进程。

           否则,表明长度为2^i的空闲分区已经耗尽,则在分区大小为2^(i+1)的空闲分区链表中寻找。

           若存在 2^(i+1)的一个空闲分区,则把该空闲分区分为相等的两个分区,这两个分区称为一对伙伴,其中的一个分区用于配,   而把另一个加入分区大小为2^i的空闲分区链表中。

           若大小为2^(i+1)的空闲分区也不存在,则需要查找大小为2^(i+2)的空闲分区, 若找到则对其进行两次分割:

                  第一次,将其分割为大小为 2^(i+1)的两个分区,一个用于分配,一个加入到大小为 2^(i+1)的空闲分区链表中;

                  第二次,将第一次用于分配的空闲区分割为 2^i的两个分区,一个用于分配,一个加入到大小为 2^i的空闲分区链表中。

          若仍然找不到,则继续查找大小为 2^(i+3)的空闲分区,以此类推。

          由此可见,在最坏的情况下,可能需要对 2^k的空闲分区进行 k 次分割才能得到所需分区。

          与一次分配可能要进行多次分割一样,一次回收也可能要进行多次合并,如回收大小为2^i的空闲分区时,若事先已存在2^i的空闲分区时,则应将其与伙伴分区合并为大小为2^i+1的空闲分区,若事先已存在2^i+1的空闲分区时,又应继续与其伙伴分区合并为大小为2^i+2的空闲分区,依此类推。
            在伙伴系统中,其分配和回收的时间性能取决于查找空闲分区的位置和分割、合并空闲分区所花费的时间。与前面所述的多种方法相比较,由于该算法在回收空闲分区时,需要对空闲分区进行合并,所以其时间性能比前面所述的分类搜索算法差,但比顺序搜索算法好,而其空间性能则远优于前面所述的分类搜索法,比顺序搜索法略差。 需要指出的是,在当前的操作系统中,普遍采用的是下面将要讲述的基于分页和分段机制的虚拟内存机制,该机制较伙伴算法更为合理和高效,但在多处理机系统中,伙伴系统仍不失为一种有效的内存分配和释放的方法,得到了大量的应用。

    3.4 内存紧缩(内存碎片化处理)

              内存紧缩:将各个占用分区向内存一端移动,然后将各个空闲分区合并成为一个空闲分区。

            这种技术在提供了某种程度上的灵活性的同时,也存在着一些弊端,例如:对占用分区进行内存数据搬移占用CPU时间;如果对占用分区中的程序进行“浮动”,则其重定位需要硬件支持。

              紧缩时机:每个分区释放后,或内存分配找不到满足条件的空闲分区时。

           

                                   图8.12

          堆结构的存储管理的分配算法:

          在动态存储过程中,不管哪个时刻,可利用空间都是-一个地址连续的存储区,在编译程序中称之为"堆",每次分配都是从这个可利用空间中划出一块。其实现办法是:设立一个指針,称之为堆指针,始终指向堆的最低(或锻联)地址。当用户申请N个单位的存储块时,堆指针向高地址(或 低地址)称动N个存储单位,而移动之前的堆指针的值就是分配给用户的占用块的初始地址。例如,某个串处理系统中有A、B、C、D这4个串,其串值长度分别為12,6,10和8. 假设堆指针free的初值为零,则分配给这4个串值的存储空间的初始地址分别为0.12.18和 28,如图8.12(a)和(b)所示,分配后的堆指针的值为36。 因此,这种堆结构的存储管理的分配算法非常简单

         释放内存空间执行内存紧缩:

         回收用户释放的空闲块就比较麻烦.由于系统的可利用空间始终是一个绝址连续的存储块,因此回收时必须将所释放的空间块合并到整个堆上去才 能重新使用,这就是"存储策缩"的任务.通常,有两种做法:

          一种是一旦有用户释放存储块即进行回收紧缩,例始,图8.12 (a)的堆,在c串释放存储块时即回收紧缩,例如图8.12 (c)的堆,同时修改串的存储映像成图8.12(d)的状态;

         另一种是在程序执行过程中不回收用户随时释放的存储块,直到可利用空同不够分配或堆指针指向最高地址时才进行存储紧缩。此时紧缩的目的是将堆中所有的空间块连成一块,即将所有的占用块部集中到 可利用空间的低地地区,而剩余的高地址区成为一整个地继连续的空闲块,如图8.13所示,其中(a)为紧缩前的状态,(b)为紧缩后的状态•

          

                         图8.13  a 紧缩前 b紧缩后

           和无用单元收集类似,为实现存储紫编,首先要对占用块进行“标志”,标志算法和无用单元收集类同(存储块的结构可能不同),其次需进行下列4步雄作:

          (1)计算占用块的新地址。从最低地址开始巡査整个存储空间,对每一个占用块找到它在紧缩后的新地址。 为此,需设立两个指针随巡查向前移动,这两个指针分别指示占用 块在紧缩之前和之后的原地址和新地址。因此,在每个占用块的第-·个存储单位中,除了 设立长度域(存储该占用换的大小)和标志域(存储区别该存储块是占用块或空闲块的标 志)之外,还需设立一个新地址城,以存储占用块在紧缩后应有的新地址,即建立一张新, 旧地址的对照表m

           (2)修改用户触初始变量表,以便在存储紧缩后用户程序能继续正常运行*。

           (3)检查每个占用块中存储的数据, 若有指向其他存储换的指针,则需作相应修改.

           (4)将所有占用块迁移到新地址走,这实质上是作传送数据的工作。

           至此,完成了存储紧缩的操作,最后,将堆指针赋以新值(即紧缩后的空闲存储区的最低地址)。

           可见,存储紧缩法比无用单元收集法更为复杂,前者不仅要传送数据(进行占用块迁移),而且还有需要修改所有占用块中的指针值。因此,存储紧缩也是个系统操作,且非不得已就不用。

     

    3.5 覆盖技术

            引入覆盖 (overlay)技术的目标是在较小的可用内存中运行较大的程序。这种技术常用于多道程序系统之中,与分区式存储管理配合使用。

           覆盖技术的原理:一个程序的几个代码段或数据段,按照时间先后来占用公共的内存空间。将程序必要部分(常用功能)的代码和数据常驻内存;可选部分(不常用功能)平时存放在外存(覆盖文件)中,在需要时才装入内存。不存在调用关系的模块不必同时装入到内存,从而可以相互覆盖。

           在任何时候只在内存中保留所需的指令和数据;当需要其它指令时,它们会装入到刚刚不再需要的指令所占用的内存空间;

           如在同一时刻,CPU只能执行B,C中某一条。B,C之间就可以做覆盖。

          

     

           覆盖技术的缺点是编程时必须划分程序模块和确定程序模块之间的覆盖关系,增加编程复杂度;从外存装入覆盖文件,以时间延长换取空间节省。

          覆盖的实现方式有两种:以函数库方式实现或操作系统支持。

    3.6 交换技术

          交换 (swapping)技术在多个程序并发执行时,可以将暂时不能执行的程序(进程)送到外存中,从而获得空闲内存空间来装入新程序(进程),或读人保存在外存中而处于就绪状态的程序。交换单位为整个进程的地址空间。交换技术常用于多道程序系统或小型分时系统中,因为这些系统大多采用分区存储管理方式。与分区式存储管理配合使用又称作“对换”或“滚进/滚出” (roll-in/roll-out)。

          原理:暂停执行内存中的进程,将整个进程的地址空间保存到外存的交换区中(换出swap out),而将外存中由阻塞变为就绪的进程的地址空间读入到内存中,并将该进程送到就绪队列(换入swap in)。

         交换技术优点之一是增加并发运行的程序数目,并给用户提供适当的响应时间;与覆盖技术相比交换技术另一个显著的优点是不影响程序结构。交换技术本身也存在着不足,例如:对换人和换出的控制增加处理器开销;程序整个地址空间都进行对换,没有考虑执行过程中地址访问的统计特性。

    3.7 覆盖与交换比较

           1)与覆盖技术相比,交换不要求程序员给出程序段之间的覆盖结构。

           2)交换主要是在进程与作业之间进行,而覆盖则主要在同一作业或进程内进行。 另外覆盖只能覆盖那些与覆盖程序段无关的程序段。

     

    四. 物理内存非连续:页式和段式存储管理


           在前面的几种存储管理方法中,为进程分配的空间是连续的,使用的地址都是物理地址。如果允许将一个进程分散到许多不连续的空间,就可以避免内存紧缩,减少碎片。基于这一思想,通过引入进程的逻辑地址,把进程地址空间与实际存储空间分离,增加存储管理的灵活性。地址空间和存储空间两个基本概念的定义如下:

    地址空间:将源程序经过编译后得到的目标程序,存在于它所限定的地址范围内,这个范围称为地址空间。地址空间是逻辑地址的集合。

    存储空间:指主存中一系列存储信息的物理单元的集合,这些单元的编号称为物理地址存储空间是物理地址的集合。

    根据分配时所采用的基本单位不同,可将离散分配的管理方式分为以下三种:
    页式存储管理、段式存储管理和段页式存储管理。其中段页式存储管理是前两种结合的产物。

    页式和段式管理区别

    页式和段式系统有许多相似之处。比如,两者都采用离散分配方式,且都通过地址映射机构来实现地址变换。但概念上两者也有很多区别,主要表现在:

          1)、需求:是信息的物理单位,分页是为了实现离散分配方式,以减少内存的碎片,提高内存的利用率。或者说,分页仅仅是由于系统管理的需要,而不是用户的需要。段是信息的逻辑单位,它含有一组其意义相对完整的信息。分段的目的是为了更好地满足用户的需要。

        一条指令或一个操作数可能会跨越两个页的分界处,而不会跨越两个段的分界处。

         2)、大小:页大小固定且由系统决定,把逻辑地址划分为页号和页内地址两部分,是由机器硬件实现的。段的长度不固定,且决定于用户所编写的程序,通常由编译系统在对源程序进行编译时根据信息的性质来划分。

         3)、逻辑地址表示:页式系统地址空间是一维的,即单一的线性地址空间,程序员只需利用一个标识符,即可表示一个地址。分段的作业地址空间是二维的,程序员在标识一个地址时,既需给出段名,又需给出段内地址。

         4)、比页大,因而段表比页表短,可以缩短查找时间,提高访问速度。

     

    五. 页式存储管理


    5.1 基本原理

            将程序的逻辑地址空间划分为固定大小的页(page),而物理内存划分为同样大小的页框(page frame)。程序加载时,可将任意一页放人内存中任意一个页框,这些页框不必连续,从而实现了离散分配。该方法需要CPU的硬件支持,来实现逻辑地址和物理地址之间的映射。在页式存储管理方式中地址结构由两部构成,前一部分是页号,后一部分为页内地址w(位移量),如图4所示:

          

          页式管理方式的优点是:

           1)没有外碎片,每个内碎片不超过页大比前面所讨论的几种管理方式的最大进步是,

           2)一个程序不必连续存放。

           3)便于改变程序占用空间的大小(主要指随着程序运行,动态生成的数据增多,所要求的地址空间相应增长)。

          缺点是:要求程序全部装入内存,没有足够的内存,程序就不能执行。

    5.2 页式管理的数据结构

             在页式系统中进程建立时,操作系统为进程中所有的页分配页框。当进程撤销时收回所有分配给它的页框。在程序的运行期间,如果允许进程动态地申请空间,操作系统还要为进程申请的空间分配物理页框。操作系统为了完成这些功能,必须记录系统内存中实际的页框使用情况。操作系统还要在进程切换时,正确地切换两个不同的进程地址空间到物理内存空间的映射。这就要求操作系统要记录每个进程页表的相关信息。为了完成上述的功能,—个页式系统中,一般要采用如下的数据结构。

            进程页表:完成逻辑页号(本进程的地址空间)到物理页面号(实际内存空间,也叫块号)的映射。
            每个进程有一个页表,描述该进程占用的物理页面及逻辑排列顺序,如图:

           

                                     图4-1 页表

            物理页面表:整个系统有一个物理页面表,描述物理内存空间的分配使用状况,其数据结构可采用位示图和空闲页链表

            对于位示图法,即如果该页面已被分配,则对应比特位置1,否置0.

           

                                      图4-2 页面表

            请求表:整个系统有一个请求表,描述系统内各个进程页表的位置和大小,用于地址转换也可以结合到各进程的PCB(进程控制块)里。如图:

          

                                           图4-3 请求表

    5.3 页式管理地址变换

           在页式系统中,指令所给出的地址分为两部分:逻辑页号和页内地址。

           原理:CPU中的内存管理单元(MMU)按逻辑页号通过查进程页表得到物理页框号,将物理页框号与页内地址相加形成物理地址(见图4-4)。

            逻辑页号,页内偏移地址->查进程页表,得物理页号->物理地址:

           

                                           图4-4 页式管理的地址变换

           上述过程通常由处理器的硬件直接完成,不需要软件参与。通常,操作系统只需在进程切换时,把进程页表的首地址装入处理器特定的寄存器中即可。一般来说,页表存储在主存之中。这样处理器每访问一个在内存中的操作数,就要访问两次内存:

           第一次用来查找页表将操作数的 逻辑地址变换为物理地址;

           第二次完成真正的读写操作。       

          这样做时间上耗费严重。为缩短查找时间,可以将页表从内存装入CPU内部的关联存储器(例如,快表) 中,实现按内容查找。此时的地址变换过程是:在CPU给出有效地址后,由地址变换机构自动将页号送人快表,并将此页号与快表中的所有页号进行比较,而且这 种比较是同时进行的。若其中有与此相匹配的页号,表示要访问的页的页表项在快表中。于是可直接读出该页所对应的物理页号,这样就无需访问内存中的页表。由于关联存储器的访问速度比内存的访问速度快得多。

     

     

    六. 段式存储管理


    6.1 基本原理

            在段式存储管理中,将程序的地址空间划分为若干个段(segment),这样每个进程有一个二维的地址空间。在前面所介绍的动态分区分配方式中,系统为整个进程分配一个连续的内存空间。而在段式存储管理系统中,则为每个段分配一个连续的分区,而进程中的各个段可以不连续地存放在内存的不同分区中。程序加载时,操作系统为所有段分配其所需内存,这些段不必连续,物理内存的管理采用动态分区的管理方法。

          在为某个段分配物理内存时,可以采用首先适配法、下次适配法、最佳适配法等方法。

          在回收某个段所占用的空间时,要注意将收回的空间与其相邻的空间合并。

          段式存储管理也需要硬件支持,实现逻辑地址到物理地址的映射。

          程序通过分段划分为多个模块,如代码段、数据段、共享段:

          –可以分别编写和编译

          –可以针对不同类型的段采取不同的保护

          –可以按段为单位来进行共享,包括通过动态链接进行代码共享

          这样做的优点是:可以分别编写和编译源程序的一个文件,并且可以针对不同类型的段采取不同的保护,也可以按段为单位来进行共享。

           总的来说,段式存储管理的优点是:没有内碎片,外碎片可以通过内存紧缩来消除;便于实现内存共享。缺点与页式存储管理的缺点相同,进程必须全部装入内存。

    6.2 段式管理的数据结构

             为了实现段式管理,操作系统需要如下的数据结构来实现进程的地址空间到物理内存空间的映射,并跟踪物理内存的使用情况,以便在装入新的段的时候,合理地分配内存空间。

           ·进程段表:描述组成进程地址空间的各段,可以是指向系统段表中表项的索引。每段有段基址(baseaddress),即段内地址。

            在系统中为每个进程建立一张段映射表,如图:

            

           ·系统段表:系统所有占用段(已经分配的段)。

          

           ·空闲段表:内存中所有空闲段,可以结合到系统段表中。

    6.3 段式管理的地址变换

                                 

                                                                      图4—5 段式管理的地址变换

            在段式 管理系统中,整个进程的地址空间是二维的,即其逻辑地址由段号和段内地址两部分组成。为了完成进程逻辑地址到物理地址的映射,处理器会查找内存中的段表,由段号得到段的首地址,加上段内地址,得到实际的物理地址(见图4—5)。这个过程也是由处理器的硬件直接完成的,操作系统只需在进程切换时,将进程段表的首地址装入处理器的特定寄存器当中。这个寄存器一般被称作段表地址寄存器。

     

    展开全文
  • 1、操作系统内存管理——分段

    千次阅读 2017-08-12 10:47:44
    操作系统内存管理——分段
  • 2、操作系统内存管理——分页

    千次阅读 2017-08-12 17:34:05
    操作系统内存管理——分页
  • 操作系统内存管理浅见

    千次阅读 2013-09-23 10:47:14
    操作系统内存管理浅见  我们举32位机,2G内存的计算机作为例子。32位指出CPU中ALU可以处理的位数,也指出地址线的位数,可以访问的内存为2的32次方,也就是4G内存,这里的4G内存指虚拟内存。它和你的2G物理内存间...
  • 在进入正题前先来谈谈操作系统内存管理机制的发展历程,了解这些有利于我们更好的理解目前操作系统的内存管理机制。 一 早期的内存分配机制  在早期的计算机中,要运行一个程序,会把这些程序全都装入内存,...
  • 操作系统内存管理——段页式(虚拟内存)
  • 【原创】WindowsCE操作系统内存管理总结 0 概述 Windows CE是一个32位的嵌入式操作系统,因此运行在Windows CE上的应用程序具有32位的寻址能力。 内存管理: 1 物理内存 RAM为操作系统和应用程序提供运行...
  • DRAM基本知识及操作系统内存管理策略一、DRAM工作原理概述二、内存分区1.固定分区(Equal-size partitions)2.动态分区三、虚拟内存置换策略 一、DRAM工作原理概述 DRAM(Dynamic Random Access Memory)即动态随机...
  • 【转】操作系统内存管理机制 在进入正题前先来谈谈操作系统内存管理机制的发展历程,了解这些有利于我们更好的理解目前操作系统的内存管理机制。 一 早期的内存分配机制 在早期的计算机中,要运行一个程序,会...
  • 操作系统内存管理——分区、页式、段式管理 1. 内存管理方法  内存管理主要包括虚地址、地址变换、内存分配和回收、内存扩充、内存共享和保护等功能。  2. 连续分配存储管理方式  连续分配...
  • 操作系统内存管理——页面的换入换出
  • 操作系统内存管理——分区、页式、段式管理 计算存储的层次结构: 当前技术没有能够提供这样的存储器,因此大部分的计算机都有一个存储器层次结构,即少量的非常快速、昂贵、易变的高速缓存(cache);若干兆字节...
  • 操作系统内存管理概述

    千次阅读 2017-01-06 16:03:43
    概述存储器分为内存和外存。主存就是内存,外存也称为辅存,就是磁盘,磁带机等外部设备。主存是和CPU通过总线相连的,CPU...我们今天的问题是,操作系统磁盘中的数据怎么装载进内存中呢?对于系统区,当机器开机时,系
  • 内存管理 分区 分页 分段 我们知道进程运行的话需要记载在内存中,并占用处理及来执行程序。那么计算机是怎么对内存进行分配和管理的? 首先操作系统把内存分区。每个区里又分页,每个页里又分表。 整个操作...
  • 操作系统内存管理实验

    千次阅读 2018-06-28 11:50:24
    #define DEFAULT_MEM_SIZE 1024 /*默认内存的大小*/ #define DEFAULT_MEM_START 0 /*默认内存的起始位置*/ /* 内存分配算法 */ #define MA_FF 1 #define MA_BF 2 #define MA_WF 3 int mem_size=DEFAULT_MEM_SIZE;...
  • 操作系统 内存管理 知识点

    千次阅读 2018-02-27 23:50:40
    操作系统把用户程序指令中的相对地址变换成为所在存储中的绝对地址的过程地址重定位实现了:从逻辑地址到物理地址的转换按照重定位时机分类:静态重定位、动态重定位地址的静态重定位定义:在程序运行之前,为用户.....
  • 当面临这些问题的时候,有两个关键词无法绕开,那就是并行和并发。 首先,要先了解几个概念:  1、进程是程序的一次执行。  2、进程是资源分配的基本单位。... 6、操作系统内存管理模块:管理物...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 27,027
精华内容 10,810
关键字:

操作系统内存管理