电脑中所有运行的程序都需要经过内存来执行,如果执行的程序很大或很多,就会导致内存消耗殆尽。为了解决这个问题,WINDOWS运用了虚拟内存技术,即拿出一部分硬盘空间来充当内存使用,这部分空间即称为虚拟内存;

虚拟内存

电脑中所有运行的程序都需要经过内存来执行,如果执行的程序很大或很多,就会导致内存消耗殆尽。为了解决这个问题,WINDOWS运用了虚拟内存技术,即拿出一部分硬盘空间来充当内存使用,这部分空间即称为虚拟内存;

操作系统将内存抽象成地址空间,每个程序都有着自己的地址空间,地址空间会被分成很多个块,每个块称之为一页,这些页会被映射到物理内存,这样就可以实现虚拟地址空间间接的使用物理内存。但是所有的页并不一定必须映射到物理内存,当程序引用了不在物理内存的页时,这时硬件执行必要的映射,将缺失的部分装入物理内存并重新执行失败的指令。这个特点实现了一个程序不用完全调入内存也可以正常运行。

页面置换算法

程序在运行的时候,如果要访问的页面不在内存中,就会发生缺页中断从而将页调入内存中,此时如果内存已经无空闲的内存,系统必须从内存中调出一个页面到磁盘对换区来腾出空间。

最佳(OPT)

选出的页面将是最长时间不访问的,这时一种理论上的算法,即下次访问它的时间相比其它页面间隔的时间最长;但是现实中并不知道什么页面的访问将会间隔最长;

最近最久未使用(LRU)

无法知道时间,但是可以知道某个页面的使用情况,如果已经使用的页面长久未使用,则将这个页面进行置换;

需要在内存中维护一个链表,每次有一个页面被使用,就将该链表的头设置成该页,因此链表的尾部就是长久未使用的页面;缺点就是每次访问都要对链表有一个更新。代价高;

最近未使用(NRU)

这种算法为每一个页设置了两个状态位,如果该页被使用,R = 1;如果该页被修改设置M = 1;R会定时清理成0;

根据这个算法,M和R共有4中状态:
R M
0 0
0 1
1 0
1 0
每次进行访问的时候会优先选择R = 0,且被修改的脏页面,即 R = 0 M = 1;

先进先出

优先置换出最先进入的页面,此算法不适合使用

第二次机会

对先进先出的修改,当页面被访问的时候,设置该页面 R = 1,需要替换的时候,检查老页面(即最先进入的页面),如果老页面 R = 1,则将 R = 0,将该页放进链表的尾端,并修改它的装入时间(该页面不是最老的,原先第二个页面成为了最老的,依次类推)然后继续从链表的头部进行遍历页查找可以置换的页。如果 R = 0,则说明该页面很久没被访问。

此种算法同样使用了链表,每次进行置换的时候需要进行移动链表中的页。

时钟

此种算法时利用了环形链表对单项链表的改进,同时使用一个指针一直指向最老的页面。

分段

分段是将内存划分成多个段落,每个段落的长度可以是不同的。且虚拟地址中的空间未使用的空间并不会映射到物理内存中,只有使用的时候 才会映射到物理内存;

虚拟空间分为如下段:

  • 文本段
    • 文本段即代码段 ,进程启动的时候会将程序的代码加载到物理内存中,文本段映射到这片物理内存;
  • 初始化数据
    • 包含了全局变量和静态变量,这些 程序 是在程序运行之前就已经确定的,因此可以 提前加载到内存中;
  • 未初始化数据
    • 即未初始化的全局变量和静态变量,这些变量只有在 程序运行的时候才会被赋值;
    • 进程每次调用 一次函数,都将 该函数分配成一个栈帧,栈帧中包含了该函数的局部变量、参数值、返回值 。通常编译器会将函数 的参数放入寄存器中优化程序,只有寄存器放不下的参数才会放进 栈帧中保存;
    • 程序运行的时候,变量的值以及 动态请求分配的内存都在该 内存段中;
  • 内核段
    • 操作系统中内核 运行时 时所占用内存在各进程虚拟 地址空间地址上的映射,所有的进程 都有,且 映射地址相同;

      除了堆内存,其它段都是 自动填充分配的,用户无法控制这些内存的使用,堆内存段是用户使用的自由内存区域

程序的地址空间分成多个拥有独立地址空间的段,每个段上的地址空间划分成多个页。分段用于数据的共享和保护;

分页和分段的比较

  • 分页透明,分段需要进行程序员进行显示划分;
  • 分页是一维地址空间,分段是二维的;
  • 页的大小不可变,段的大小可变;
  • 分页主要用于虚拟地址的实现,分段为了程序和数据可以被划分逻辑上的独立的地址空间有助于共享和保护;