个人操做系统复习——存储器管理

  上篇博客介绍了处理机调度的相关知识——个人操做系统复习——处理机调度,本篇开始讲跟处理机打交道最多的计算机部件——存储器。存储器包括常说的内存和外存。存储器管理,通常指的是内存管理。外存也属于存储器,不过应该算做文件管理。html

1、存储器层次分类

  存储器按存储层次分能够分为三类,分别是寄存器、主存、辅存。寄存器位于CPU内,主存又称内存,辅存即硬盘。仔细划分的话,主存还能够分为高速缓存、主存、磁盘缓存。以下图所示,层次越往上,存储介质访问速度越快,价格越贵、相对存储容量也越贵。寄存器和主存这里大概说一说,辅存(外存)就留到文件系统的时候再说。算法

  

  (1)寄存器

  寄存器位于CPU内,是CPU的组成部分。它是计算机系统内CPU访问速度最快的存储部件,彻底能与CPU协调工做。不过价格太贵,只能作得很小。寄存器是用来存放系统最常访问的数据,如,指令寄存器用来存放从内存读到的正在执行的指令,程序计数器存放下一条指令所在单元的地址。其本质就是用来存放供CPU最频繁访问的一批数据。寄存器就是为了解决CPU访问主存速度过慢的问题。一般,CPU从主存读取数据,放入寄存器内,以便频繁访问。缓存

  (2)主存

  主存即内存。CPU能够经过指令直接存取主存中的数据,因此CPU对主存的访问速度也很快,不过这个速度也远低于CPU的执行速度。为了解决这个问题,引入了寄存器和高速缓存。高速缓存是什么?高速缓存也是属于内存,不过它与一般的主存的实现形式不一样,它通常是由静态存储芯片(SRAM)组成,访问速度比主存高得多, 接近于CPU的速度。而主存一般使用动态MOS随机读写存储器DRAM组成,速度比SRAM快得多。高速缓存的做用就是存放主存中一些常常被访问的信息。磁盘缓存的本质就是主存划分的一个小区域,为了减小CPU透过I/O读取磁盘机的次数,提高磁盘I/O的效率,用一块区域来储存存取较频繁的磁盘内容。数据结构

 

2、程序的装入和连接

  程序装入就是把程序和数据放入内存。程序也不是一开始就有的。这里指的程序是最终在内存中运行的模块——装入模块。那么一份源代码是怎么变成可运行的程序的呢?学过C、C++的同窗对这个最了解。首先是把源代码用编译程序编译成目标模块,每一份源代码文件对应一个目标模块。而后用连接程序将目标模块和程序所须要的库函数连接起来,变成一个可运行的程序。这个可运行的程序,实质是编译连接后的机器指令,CPU能够运行这些机器指令。程序运行时,装入模块将其放入内存并运行。其中,将这些机器指令何其指向的资源装入内存有3种方式:并发

  (1)装入:

    1)绝对装入方式(Absolute Loading Mode)函数

  程序中使用的地址是直接指向内存的绝对地址,那么在把程序装入内存的时候,不须要对程序地址作任何修改,这种装入方式就叫作绝对装入方式。绝对装入方式只能将程序装入到内存中指定的位置,它只适合单道处理环境,这样就不会有内存冲突了。优化

    2)可重定位装入方式(Relocation Loading Mode)ui

  可重定位装入方式指的是,将程序装入内存的时候,将程序地址都相对于内存当前地址偏移。这时程序中的地址都是相对地址。值得注意的是,装入时对程序中指令和数据地址的修改过程叫作重定位。spa

    3)动态运行时装入方式(Dynamic Run-time Loading)操作系统

  若是程序在运行时位置须要改变,应该采用动态运行时装入方式。动态运行时装入方式指的是程序中的相对地址并不在装入时就转换成内存中的绝对地址,而是等到真正运行的时候才会转换。

  (2)连接:

  与程序装入相对应的是程序的连接方式。程序的连接方式也有3种方式,分别是静态连接方式、装入时动态连接和运行时动态连接。分别对应的是程序连接时的3个时间。其中静态连接是程序的目标模块在装入以前就连接好,而装入时动态连接,顾名思义,就是目标模块实在装入内存的时候动态的进行连接,这种方式连接的程序的目标模块是分开存放的,若一个目标模块须要连接给其余多个模块是很是方便的。而在静态连接方式中要实现这个功能,须要其余多个模块都含有该模块的拷贝。

 

3、内存分配方式——连续分配方式

  将内存分配给程序,最典型的方式就是将一个连续的内存空间分配给程序,这就是连续分配方式。这种分配方式细分能够分为单一连续分配、固定分区分配、动态分区分配和动态重定位分区分配。须要了解的是,前面的程序装入内存的过程就是典型的内存分配。就是说,内存的分配一般多是动态,在程序运行过程当中,一般伴随着动态的内存建立和内存回收,其中还涉及到不少缓存、优化之类的策略。在各类内存分配和回收的过程当中,会产生不少空余碎片。内存分配就是要尽量利用内存空间,避免内存浪费。

  (1)单一连续分配

  这种分配方式就是简单的把内存分为系统区和用户区,系统区给操做系统用,用户区给用户用。这种分配方式很是简单,并未考虑多用户内存冲突和多任务内存冲突的状况,因此只适用于单用户、单任务的OS。值得注意的是,系统区一般是分配在内存的低址部分。

  (2)固定分区分配

  这种分配方式就是将内存划分为若干固定大小的区域,区域的大小是事先划分好的,每一个区域装入一道做业、程序,这样多任务内存冲突的问题就解决了。这种划分方法适用于多道批处理系统——多任务并发的状况。可是,因为每一个分区大小固定,存储空间的浪费是必然的。

  (3)动态分区分配

  这种分配方式就是根据进程的实际须要,动态的分配内存空间。这种分配方式有3个问题须要注意。一、须要有一种数据结构来描述空闲分区和已分配分区的状况。二、须要按照必定的分配算法从空闲分区中选择空间来分配。三、须要有合适的分区分配和内存回收操做:

    1)描述空闲分区的数据结构:

    有2种数据结构能够描述空闲分区的数据结构,分别是空闲分区表和空闲分区链。其中,分区表很容易理解,分区链指的是经过在空闲分区的首尾设置2个指向其余空闲分区的指针,造成一个空闲分区的链,用来记录空闲的分区。

    2)分区分配算法:

    • 首次适应算法(first fit):分区链以地址递增的次序连接;分配内存时,从链首开始,查找到一个大小能知足要求的空闲分区就中止。这个算法说白了就先分配内存的低址部分,再分配高址部分。
    • 循环首次适应算法(next fit):这个分配算法与首次适应算法的区别在于,它分配内存时,不是从链首开始查找,而是从上次找到的空闲分区的下一个分区开始查找。
    • 最佳适应算法(best fit): 分区链以从小到大的顺序连接;分配内存时,从链首开始,查找到一个能知足要求的空闲分区就中止。
    • 最坏适应算法(worst fit): 分区链以从大到小的顺序链接;与最佳适应算法相反,每次都挑最大的空闲区来分配。
    • 快速适应算法(quick fit): 将空闲区根据大小进行分类,每一种类别单独设立一个链表。同时,用一个管理索引表来管理这些链表。那么分配内存的时候只须要查询管理索引表就好了,无需遍历链表,速度很是快。缺点是,这个算法须要一直维护着链表和管理索引表,须要必定系统开销。

    3)内存分配和回收:

    在分配空闲分区的时候,值得注意的是,一般空闲分区会有一个“不可再分割的剩余分区大小”的属性,规定了,当空闲分区所剩属性小于它的时候,分区不容许再继续分割,分区也将从空闲分分区链表中移除。

    内存回收的时候,值得注意的是,若回收的内存区与某个空闲分区相邻接,那么须要将它们合并。不然,须要为回收区创建新的空闲分区。 

    4)伙伴系统:

    咱们知道1G的内存有220个字节,有224个字。那么根据指数,最多分为24个空闲分区链表。假设一个应用程序申请2MB的内存,2MB即215个字的大小,这时候查找大小为215的空闲分区链表,若找不到,那么查找大小为216的空闲分区链表,若216的空闲分区链表存在,那么把它分红2个,一个分配给请求,另外一个分配为215的空闲分区链表,若若216的空闲分区链表不存在,那么继续日后查找,以此类推。

  (4)可重定位分区分配

    因为程序、资源间会有不少碎片,浪费了内存空间,可重定位分区分配就是为了解决这个问题,它能够直接移动内存中的程序、资源,使内存变得紧凑,同时也不影响程序的正常运行。可重定位分区分配要求程序的装入方式是动态运行时装入方式。程序装入内存后,全部地址仍旧是相对地址,直到运行时才会转变为绝对地址。程序在寄存器中有一个重定位寄存器,用来存放程序在硬盘中的实际地址的首地址。那么将程序在内存中的绝对地址移动,只须要移动后,改变重定位寄存器的值便可。这咱们常常用的“磁盘碎片清理”就是同样的效果。

  (5)对换

    对换是一个须要了解一下的概念。还记得前面咱们讲进程调度的时候,有一个特殊的调度类型,叫作中级调度。中级调度就是让暂时不能运行的进程挂起,释放内存资源,并把它们调到外存上去等待,这种操做,在内存看来,就叫对换。以进程为单位的对换叫进程对换。对换的状况下,外存中必须分配必定的区域用来存放对换的内存资源,叫作对换区。这个对换区本质是虚拟存储器,这个后面会讲。

 

4、内存分配方式——离散分配方式

  连续的分配方式会产生不少碎片。离散的分配方式是将进程、资源装入不相邻的多个分区的内存分配方式。这种分配方式按照分配的单位是“页”仍是“段”,分为分页存储管理、分段存储管理以及段页式存储管理。

 (1)分页存储管理

  分页存储管理是根据程序做业中的“页”为单位离散分配内存的管理。

  1)页面(页)。

  分页存储管理的内存分配单位是页。什么是页?页就是一段指定大小的内存块。分页存储管理就是按照必定大小把进程的逻辑地址空间分红若干份,每一份就是一个页,把他们编号。而后按照页的大小把内存分为若干物理块,并编号。页的大小一般是512B到8KB之间。

  2)页表。

  每个进程都有一张页表,用来记录进程的页号对应的物理块号。进程运行时,CPU会根据程序的逻辑地址和页号大小从页表找到实际的物理块和实际的物理地址。页表是常常被CPU访问的,CPU常常须要先访问页表再根据页表的地址访问内存,因此通常会设置一个“联想寄存器”,又称“块表”,存放最近频繁访问的页表。若是系统的内存特别大,页表中页面的逻辑地址就会特别大,就须要用多层的页表结构来对应物理块号。这种状况下,CPU会根据程序的逻辑地址和页面大小从多层的外部页表找到指定的页表,再从页表中找到实际的物理块和物理地址。

(2)分段存储管理

  分段存储管理是根据程序做业中的“段”为单位离散分配内存的管理。

  1)段。

  段指的是程序、做业中的一组逻辑信息。例如:全局变量能够设为一个段;每一个函数的局部变量能够设为一个段;每一个函数的代码部分能够设置为一个段。这样作有什么意义呢?至关于将程序中的这种逻辑信息根据大小离散的存储在内存中,而对于逻辑信息自己而言,他们在内存中是连续的,不会被分割的,这样有利于对逻辑信息的处理,如信息共享、信息保护等。

  2)段表。

  与页表相似的,每一个进程都有一张段表,用来记录程序中每一个段对应的物理位置。段表中每一个记录都记录了段的物理地址和段的长度。一样,因为段表常常须要被访问,有些系统会把段表放在寄存器中。

  (PS:值得注意的是,运行时动态连接要求内存使用分段存储管理。)

(3)段页式存储管理

  段页式存储管理是根据“段”为单位,再将“段”细分为“页”,以这个为单位离散分配内存的管理。原理与分页、分段存储管理相似。  

 

5、虚拟存储器管理

   对于内存的连续分配方式,上文有一个“对换”的概念,就是将暂时不用的内存资源从内存中移出,放到外存的对换区中。当须要该内存资源的时候,须要及时可以把该内存资源从外存中移入内存。这里的对换区其实就是虚拟存储器。讲到虚拟存储器有须要了解一下程序执行的局部性原理,总结下来就是:

  • 程序的执行过程当中,大部分的指令是执行一次或不多执行的,CPU主要是在执行一小部分指令。
  • 程序的执行过程当中,大部分资源是不多被访问的。

  因此,程序一次性装入内存,而实际上大部份内存资源是被浪费的。基于这种状况,不必把全部资源都一次性装入内存。仅须要将程序当前须要的运行的段(页)装入内存便可。若是程序运行时访问到内存中不存在的段(页),这种现象叫“缺段”(却页),这时候须要根据必定算法从外存的虚拟存储区将缺失的资源当即装入内存。

  这里有一个补充知识,见http://zhidao.baidu.com/question/86215203.html:

   至于页表的问题是这样的,在系统初始化时,是直接对物理内存进行访问的,不通过页表,这是的工做模式叫实模式,等页表在内存中创建好了,再切换的保护模式,在保护模式就出现了虚拟地址向物理地址转译的过程了。 

  CPU有两种工做模式,一个是实模式,就是直接访问物理内存,不分页的。另外一个是保护模式,就是分页的,并且存在虚拟地址。保护模式下又有特权模式和用户模式两种。关系是这样子的。

  我给你讲,只要发生缺页中断,就会陷入内核,只是就进入了特权模式,控制权交给了操做系统,这一系列过程都是硬件完成的。至于换页使软件完成的,就是操做系统负责调页。MMU只是负责把虚拟地址转译成物理地址,他只能作这个,纯硬件实现的。操做系统有调页算法,就是在空闲的页找出来一个,把须要的内容从磁盘读出来,放到内存里,而后让进程从新运行那条指令。一切继续,就像没有缺页过同样。若是没有空闲的,就把最不常用的一页替换掉。

 

 参考:《计算机操做系统(汤子瀛)》

相关文章
相关标签/搜索