页面置换算法
当发生缺页中断的时候, 系统会在内存中选择一个页面将其换出内存, 而当换出内存的时候如果该页面的内容在内存中发生修改,则必须将该新数据重新写回到磁盘, 然后再将需要换进的数据覆盖掉原来的数据, 而当该数据在内存中没有被修改的时候, 此时就直接用需要换进的内存的内容替换掉要淘汰的数据的内容.注意在换出的时候必须选择一些使用频率较低的页面将其换出.
在大多数计算机中会把最近经常使用的存储块保存到一个高速缓存区中, 当这个高速缓存区装满的时候就需要选择一些存储块将其丢弃
1. 最优页面置换算法
每一个页面用调用该页面前所需要执行的指令数进行标记, 在进行页面置换的时候选择该数字最大的进行换出. 这种算法虽然性能等各方面都比较好, 但是由于操作系统无法获知某个页面要在什么时候被调用, 因此不能实现, 但是可以用来评估一个页面置换算法的性能优劣
2. 先进先出页面置换算法
在先进先出页面置换算法中, 由操作系统维护当前内存中的页面,并且通过链表的形式将其组织起来, 链表的前后顺序按照调入内存的时间排序, 即最先调入内存的页面处于链表的头部, 当有一个新的页面需要访问内存的时候, 此时操作系统将处于链表头部的页面调出, 即在内存中待的最久的页面将其调出, 然后将新的页面插入到链表的尾部
3. 最近未使用页面置换算法
为使得操作系统能够获得更多的有用信息, 系统为每一个页面都设置了两个状态, 当页面被访问的时候设置 R 位, 当页面被写入的时候设置 M 位. 这些位都被放在了一个页表项中(如上图)每次访问的时候更新这些位. 因此有硬件设置这些位是非常有必要的
在系统被启动的时候, 所有的位都被清零. R 位被定期的清零, 为了区别页面是否被访问. 因此利用R位和M位可以将系统中的所有页面划分为以下三种
(0)没有被访问, 没有被修改
(1)没有被访问, 已经被修改
(2)已经访问, 没有修改
(3)已经访问, 已经修改
这样的话, 每一个页面都会有一个编号, 在进行页面置换的时候, 系统往往从当前页面中选择一个编号最小的并且将其淘汰
4. 最近最少使用页面置换算法
在内存中的页面一般在很久的时间内没有使用则该页面在未来的很久时间内也可能被使用的几率会特别小. 根据这个原理, 系统在进行页面置换的时候每次从内存中选择一个未使用时间最长的页面将其换出.
页面置换算法比较
局部分配策略和全局分配策略
局部分配策略就是每次在置换的时候选择页面在内存中生存时间最短的页面将其换出, 而全局分配策略则是从内存中随机的换出一个页面. 全局分配策略比局部分配策略要好一点.
1. 页面大小
选择小页面
选择一个正文段, 数据段或者堆栈段很有可能不会恰好转满整个内存, 平均情况下都是最后一个页面时空的. 多余的空间就被浪费, 这个被浪费的空间就叫做内部碎片. 总的来说,选择小的页面比选择大的页面浪费的内存会少一些, 但是选择小的页面也意味着内存中的页表会变得更大, 页面装入页面寄存器所花费的时间就会越长.
2. 未定义外部函数
在任何目标文件中被调用了但没有被定义过的函数就叫做未定义函数. 如 printf 函数
3. 共享库
如果一个程序被启动了两次, 大多数操作系统会自动地共享所有的代码页面. 依赖与不同的进程, 每一个进程都拥有一份私有的副本数据, 如果任何一个进程想要对这个副本数据进行修改, 操作系统变为这个进程将这个副本数据做一个拷贝, 这个拷贝的数据就是该进程私有的数据. 注意当一个共享库被装载或者使用的时候, 此时并不是将共享库中所有的内容装载进内存, 而是根据需要将需要的部分以也为单位将其装入, 因此没有被调用的函数是不会被装载进内存的.
因此共享库可以使得可执行文件更小, 并且节省内存.并且当我们在修改一个 bug 的时候, 如果共享库中的一个函数被更新了, 此时不需要重新编译这个函数程序. 就得二进制文件依然可以使用.
缺页中断处理
(1)硬件陷入内核, 在对应的堆栈中板寸程序计数器. 大多数机器将当前的指令各种信息保存在特殊的 CPU 寄存器中.
(2)启动一个汇编代码例程来保存寄存器和其他易失的信息. 这个例程往往将操作系统作为一个函数来调用.
(3)发生中断的时候, 操作系统会尝试发现需要哪个虚拟页面.
(4)当知道了虚拟地址的时候, 此时操作系统便对这个地址进行检查, 并且检查存取和保护是否一致. 如果不一致, 则操作系统向对应的进程发送一个信号, 将该进程杀死. 如果没有发生任何错误机制, 则操作系统拿着这个虚拟地址去检查时候存在一个空闲的页框, 如果没有一个空闲的页框, 那么操作系统便执行页面置换算法寻找一个页面将其换出.
(5)如果选择换出的页面被修改过, 那么系统将安排该数据写回到磁盘, 挂起缺页中断的进程.
(6)如果该页面shiganjingde,那么操作系统在磁盘中查找需要调入的页面在磁盘中的位置, 然后将该页面装入到内存中. 并将发生缺页中断的进程挂起
(7)当磁盘访问中断的时候, 此时说明该页面已经被调入到内存, 页表已经对该页进行相应的更新, 对应该页表的页框也发生了更新, 即标记为正常状态.
(8)对缺页中断的指令以及程序计数器的内容做以修改.
(9)调度引起缺页中断的进程, 操作系统返回调用它的汇编例程
(10)恢复寄存器, 返回用户态