操作系统:内存管理(一)

来源:互联网 发布:javascript 注销事件 编辑:程序博客网 时间:2024/05/29 19:24

随着多道程序系统和时分概念的普及,总有多个进程想再CPU上运行,当CPU在进程之间切换的时候,物理内存该怎么处理呢?进程之间的内存能相互隔离吗?

方法一:
当进程切换时,可以将与进程有关的PC计数器,通用寄存器以及内存中的所有内容都拷贝到磁盘中,当下次需要再次运行的时候,再将这些内容拷贝到内存中。
这种方法十分暴力直接,但可惜速度太慢。于是乎有了第二中方法

方法二:
通过抽象,让每个进程都有一块地址空间,从进程的视角来看,每一个进程的地址空间都是相同的,编码从0KB~512KB;从操作系统的角度来看,每个进程的地址空间实际上是映射到不同的物理内存上的。映射的方式就叫做内存虚拟化,属于内存管理的内容。

内存虚拟化目标

前面提到为了让进程间不相互影响,所以尝试用虚拟化内存来实现。在这里再次重申一下内存虚拟化要达到的目标:

  1. 进程之间对内存是透明的。进程可以随意使用内存,就像没有经过内存虚拟化一样;
  2. 进程就好像完全拥有自己的私有内存一样,不与其他进程共享。
  3. 效率;在时间和空间上都要尽可能高效;

虚拟化内存

内存虚拟化主要是通过抽象,让进程和用户看到的内存是相同格式,并且拥有整个内存。 进程看到的就是虚拟内存,也称之为地址空间

那么地址空间和物理内存如何进行一一对应呢?,进程如何通过虚拟内存访问到物理内存中的数据呢

Address translation

方法一:
操作系统在生成进程的时候为每一个进程都分配两个寄存器分别保存:

  • base基址:进程地址映射到物理内存的
  • bound:为该进程允许分配的最大内存大小

映射的方式很简单:
物理地址 = 虚拟地址 + base;
这种方式相对简单,但在这种情况下,需要为每个进程分配相对固定大小的内存。前面我们提到,进程中内存分为代码和静态数据去,栈内存区,堆内存区;如果为每个进程分配固定大小的内存,栈内存区和堆内存区就会相对较多没有被使用的内存。当有许多进程的时候,就会造成大量的内存浪费。(进程分配过小,进程运行将会出现异常)

那么该如何解决上述内存浪费的现象呢?

方法二:Segmentation
在方法一中,是为每一个进程保存了一个base和bound;那为什么不为每一个segment保留一个base和bound呢?在进程中,内存被分为代码区,堆内存区和栈内存区;这三个是三个相对独立的segment,我们可以为每一个segment保存base和bound,这样每个进程的堆栈区可以定制化大小,这样就解决了内存浪费的问题。

当我们标记segment的时候,我们怎么标记segment对应的是代码区,还是堆栈区呢? 这个时候可以考虑把虚拟地址的前两位弄出来,标记具体是哪一个segment,剩下的地址就表示在对应物理内存相对于base地址的偏移

虽然解决了进程里内存浪费的问题,但又有新的问题出现:当进程较多的时候,每个进程都需要分配多个segment,那这些segment之间的内存该怎么处理呢? segment的内存被回收的时候,内存又该怎么处理呢?

这里就涉及到空闲内存的管理了