大而稀疏的内存使用
对于大而稀疏的内存,在使用时不方便采用连续编址。必须使用不连续编制。通常有3种不连续编址方案:段式、段页式和页式稀疏编制。
总的来说,页式稀疏编址优于段式和段页式编制。现在操作系统都采用稀疏页编址。但是此处的不连续是针对进程逻辑空间(即进程虚址空间)的不连续性,不连续存放技术是针对物理空间的不连续。
在页式模式下,进程虚址空间的稀疏编制可能提供充裕的多处伸缩余地。用户可以不连续,可以非常稀疏,只要不冲突就行。
稀疏编址的实现是以二级页表为前提,这是因为二者都是在大虚存空间背景下采用的技术。
页分配技术
内存分配策略包括分配时机,分配数量,分配位置,调度策略
fetch 策略(何时分配与装入):有立即调页,有请调页,有预先调页3种。
- 立即调页是在进程开始执行前(即初始建立进程时)分配与装入。
- 请求调页(demand paging)是指在进程实际访问到某页时才通过发生缺页中断处理程序分配与装入该页。又称怠惰风格(lazy fashion)。
- 预先调页是指由操作系统根据一定的算法,动态预测将来最近时间内可能要访问哪些页,并在这些页被实际访问之前就预先调用它们。尽量争取在进程的每一页被实际访问之前就调入。
虚存的页式大都使用后面两种方式,而实存页式都使用立即调页。
请求调页的优点是去报了只有用到的页才能进入内存,没有用到的也不会进入内存,缺点是可能发生的缺页中断太多。尤其是进程刚开始执行的那段时间里。由于每次缺页中断差不多要发生I/O操作。而进程总要等缺页中断发挥才能继续进行。期间要经历进程状态的转换。过多的缺页中断会严重影响进程的速度。
预先调页在减少缺页中断上的效果是显而易见的,预先调页的时机一般是在缺页中断时,在调入所缺页的同时调入以后最近时间内最可能要访问的那些页。如果预先调入的这些页确实很快就被访问到了。那么缺页中断次数就会明显减少。
写时复制:
进程的创建是一个十分复杂的过程,通常的做法需要为子进程重新分配物理空间,并把父进程空间的内容全盘复制到子进程的空间中。但是这种做法的开销非常大。为了避免这些开销,现代操作系统通常采用写时复制(copy on write)。即不复制父进程的空间,而是复制父进程的页表,使父进程和子进程共享物理空间。并将这个空间的访问权限标记为只读。当父进程和子进程的某一方进行写操作时,操作系统检测到一个非法操作,这时才将要写的页进行复制。
页式实现专题讨论(5):页长和页簇化
页面大小通常为2的整数次幂,这可以简化地址映射过程中的逻辑地址分解(从逻辑地址得到逻辑页号和页内位移)和物理地址计算(从物理页号和页内位移得到物理地址)例如:如果如果页长为2的N次方b,则逻辑地址的低N位即为页内位移数,剩余的高位值即为逻辑页号。反之,从物理页号和页内位移之间得到物理地址亦然。
页面长的选择有以下考虑:页面大则内存交换区中的页内碎片也就越大,相应浪费的内存较多。但是相应的进程页表规模小,TLB表项数少。Cache 和TLB的不命中项数少。页面小则反之。
页面长由CPU(MMU)硬件规定的。不同CPU规定的页面长可能不同。目前以4KB长的页表为最常见。同一CPU规定的页面长可能有多个。
页淘汰:
页淘汰(page replacement)通常是由一个系统进程或线程来完成的,该进程成为页淘汰进程。
页淘汰的时机:当内存空间页面数低于系统所配置的最小阈值时,启动页淘汰进程,页淘汰进程被启动后就开始不停地选择和淘汰页知道内存的空闲页面数达到系统所配置的最大阈值时为止。此后,页淘汰进程进入睡眠状态,知道下次因为内存空闲页面数少于最小阈值而被再次唤醒。