3.5 分页系统中的设计问题
3.5.1 局部分配策略和全局分配策略
怎样在互相竞争的可运行程序之间分配内存。
局部页面置换算法,只在进程内部分配,如果有缺页则置换本进程内的页面。
全局页面置换算法,在所有进程所占内存分配,如果有缺页则置换所有进程中最适合的页面。
通常来说全局页面置换更好,尤其是在工作集的大小随进程运行时间发生变化时这种现象更加明显。若使用局部算法,即使有大量空闲页框存在,工作集的增长也会导致颠簸。如果工作集缩小了,局部算法又会浪费内存。
使用一个进程分配页框的算法,定期确定进程运行的数目,并为其分配内存。平均分配并不合适,因为进程大小不同,比较明智的做法是对每个进程都规定一个最下的页框数,不论多小的内存都可以运行。
当然也可以根据进程比例大小分配内存,管理内存动态分配的一种方法是使用PFF(Page Fault Frequency)缺页中断率。它指出了合适增加或者减小分配给一个进程的页面,但却完全没有说明在发生缺页中断的时候应该替换掉哪一个页面。
PFF尽力让每个进程的缺页中断率控制在可接受的范围内。
需要说明的是有些页面置换算法,只有采用局部置换策略才有意义。特别是对于工作集和WSClock算法只能针对特定进程
3.5.2 负载控制
在进程过多的情况下,必须要从内存中暂时去掉一些进程。将其交换到磁盘,并释放他们所占有的所有页面。
不过在交换进程时需要考虑交换进程的类型和其他进程的特性(IO密集型或CPU密集型)
3.5.3 页面大小
从结果来看不存在全局最优,
选择小页面:
- 随便选择一个正文段和数据段或堆栈段很可能不会恰好装满整数个页面,平均的情况下,最后一个页面中有一半是空的。多余的空间就浪费了。这样的空间浪费称为内部碎片。
- 大页面使得更多没有用的程序保存在内存中
选择大页面:
- 需要较小的页表
- 传输一个大页面和传输小页面的速度是相同的,(硬盘传输)
目前常见的页面大小是4KB。
3.5.4 分离的指令空间和数据空间
为指令(程序正文)和数据设置分离的地址空间。分别称为I空间和D空间。连接器需要知道何时使用分离的I空间和D空间。使用时需要重定位。
除了这一区别,I空间和D空间不会引入任何复杂的设计,而且™还能使可用的地址空间加倍。(为何)
3.5.5 共享页面
在大型多道程序设计系统中,几个不同的用户同时运行同一个程序是很常见的。特别地,哪些只读的页面可以共享,但是数据页面则不能共享。
通常来说共享的页面必须是只读的,如果页面的数据被修改,如果被修改了就触发操作系统陷阱。然后会生成一个该页面的副本。这个每个进程都有自己的专用副本。
3.5.6 共享库
共享库是更加通用的技术(windows下称为DLL或者动态链接库),如果程序调用了未定义外部函数(undefined externals)链接器会在库中寻找这些未定义外部函数,如果找到了则将他们加载到可执行二进制文件中。
优点:
- 大大降低可执行文件的大小
- 如果共享库中的一个函数因为bug被更新了。不需要重新编译源程序。而只要更新这个共享库就行。
不够共享库也带来了一个小问题:
不同进程对于共享库的映射的地址是不同的,编译到时候需要一个特殊的编译选项告诉编辑器,不要产生使用绝对地址的指令,相反只产生相对地址,这样只要使用相对偏移量的方式来解决地址问题。这样只是用相对偏移量的代码称为位置无关代码。
3.5.7 内存映射文件
进程可以通过发起一个系统调用,将一个文件映射到其虚拟地址空间的一部分。在多数实现中,在映射共享的页面时不会实际读入页面的内容,而是在访问页面时才会被每一页地读入,磁盘文件责备当做后备存储。当进程退出或者显式的解除文件映射时,所有被改动的页会被写回到文件中。
如果两个进程同时访问了一个问题文件。可以通过共享内存来通信。这个机制为进程间通信提供了一个高带宽通道,且这样的应用很普遍(甚至拓展到映射无名的零时文件)
3.5.8 清除策略
很多分页系统有一个称为分页守护进程(paging daemon)的后台进程,它在大多数时候睡眠,但定期唤醒已检查内存状态。如果空闲页框过少,分页守护进程通过预定的页面置换算法选择页面换出内存。分页守护进程保证至少所有空闲页框是干净的,所有空闲页框在被分配时不需要在着急写回磁盘。
实现清除策略的方法就是使用一个双指针时钟。前指针由分页守护进程控制,当它指向一个脏页面时候,就把页面协会磁盘,前指针向前移动。当它指向一个干净页面时,仅仅指针向前移动。后指针用于页面置换。就像标准时钟算法中一样。
3.5.9 虚拟内存接口
运行程序员对内存映射进控制的一个原因就是为了运行两个或者多个进程共享一部分内存。高带宽的共享称为可能。
共享页面也可以用来实现高性能的消息传递系统。一般地,传递消息的时候,数据被从一个地址空间复制到另一个地址空间,开销很大。如果进程可以控制它们的页面映射,就可以这样来发送一条消息:发送进程清除哪些包含消息的页的映射,而接受进程把它们映射进来。这里只需要复制页面的名字,而不需要复制所有数据。
另外一种高级储存管理技术是分布式共享内存。