内存
内存分页
概念
内存分页(Paging)是将物理内存划分成大小相等的固定块(通常是4KB),称为页面(Page),将逻辑地址(也称虚拟地址)按页面大小划分为大小相等的块,称为页(Page)。将每个页映射到物理内存的一个页面中。当程序访问逻辑地址时,操作系统将其转换为物理地址并进行访问。
特点
优点
- 处理器访问内存时只需要考虑页号,而不用考虑段号,这样访问地址的转换更为快速。
- 页的大小相等,使得内存分配更为灵活,可以更好地利用内存空间。
- 内存分页可以实现虚拟内存技术,将不常用的页面存储在磁盘上,以获得更多的内存空间。
缺点
- 因为页的大小是固定的,可能会浪费一些内存空间。
- 可能会出现内存碎片问题,需要使用一些算法来解决。
Belady现象
ady现象,又称为页错误率异常现象或Belady异常,是指在一些特定情况下,增加计算机系统的物理内存容量可能会导致更多的页面错误。
当一个程序在执行过程中需要访问的数据或指令不在当前的内存中时,就会发生“缺页中断”,操作系统会将缺失的页面从硬盘中加载到内存中,以便程序可以继续执行。在物理内存容量不足时,操作系统可能需要将一些页面替换出去,以便为新页面腾出空间,这就是页面置换算法的工作。Belady现象指的是,当使用某些置换算法时,在增加物理内存的情况下,缺页中断次数反而会增加。
产生Belady现象的原因是,某些置换算法对于页面访问的时间序列比较敏感,可能会出现某些情况下增加物理内存容量反而导致更多的页面置换,从而增加缺页中断的次数。例如,最近最少使用算法(LRU)
可能会在某些情况下出现Belady现象。
需要注意的是,Belady现象只在某些特定的情况下出现,一般情况下增加物理内存容量会降低缺页中断的次数,提高系统的性能。因此,在设计和优化系统时,需要根据实际情况选择合适的置换算法以及物理内存容量。
内存页置换算法
最优页面置换算法
- 每个页面都可以用在该页面首次被访问前所要执行的指令数作为标记。
- 最优页面置换算法规定应该置换标记最大的页面。每次选择淘汰的页面将是以后永不使用,或者在最长时间内不再被访问的页面,这样可以保证最低的缺页率。
- 另这个算法唯一的问题就是它是无法实现的。当缺页中断发生时,操作系统无法知道各个页面下一次将在什么时候被访问。(在最短作业优先调度算法中,我们曾遇到同样的情况,即系统如何知道哪个作业是最短的呢? )当然,通过首先在仿真程序上运行程序,跟踪所有页面的访问情况,然后在第二次运行时利用第一次运行时收集的信息是可以实现最优页面置换算法的。
最近未使用页面置换算法
- 可以用R位和M位来构造一个简单的页面置换算法: 当启动一个进程时,它的所有页面的两个位都由操作系统设置成0, R位被定期地(比如在每次时钟中断时)清零,以区别最近没有被访问的页面和被访问的页面。
- 当发生缺页中断时,操作系统检查所有的页面并根据它们当前的R位和M位的值,把它们分为4类:
- 第0类:没有被访问,没有被修改。
- 第1类:没有被访问,已被修改。
- 第2类:已被访问,没有被修改。
- 第3类:已被访问,已被修改。
NRU (Not Recently Used,最近未使用)算法随机地从类编号最小的非空类中挑选一个页面淘汰。
这个算法隐含的意思是,在最近一个时钟滴答中(典型的时间是大约20ms)淘汰一个没有被访向的已修改页面要比淘汰一个被频繁使用的“干净”页面好。NRU的主要优点是易于理解和能够有效地被实现,
先进先出页面置换算法
另一种开销较小的页面置换算法是FIFO (First-In First-Out, 先进先出)算法。
同样的思想也可以应用在页面置换算法中。由操作系统维护一个所有当前在内存中的页面的链表,最新进入的页面放在表尾,最早进入的页面放在表头。当发生缺页中断时,淘汰表头的页面并把新调入的页面加到表尾。可能会淘汰常用的页面,因此,当它应用在计算机上时也会引起同样的问题,由于这一原因,很少使用纯粹的FIFO算法。
Belady异常:当为进程分配的物理块数增大时,缺页次数不减反增的异常现象。
只有FIFO算法会产生Belady异常。另外,FIFO算法虽然实现简单,但是该算法与进程实际运行时的规律不适应,因为先进入的页面也有可能最经常被访问。因此,算法性能差。
第二次机会页面置换算法
FIFO算法可能会把经常使用的页面置换出去,为了避免这一问题,对该算法做一个简单的修改:
检查最老页面的R位。如果R位是0,那么这个页面既老又没有被使用,可以立刻置换掉; 如果是1,就将R位清0,并把该页面放到链表的尾端,修改它的装入时间使它就像刚装入的一样,然后继续搜索。
时钟页面置换算法(最近未使用算法NRU)
尽管第二次机会算法是一个比较合理的算法,但它经常要在链表中移动页面,既降低了效率又不是很有必要。一个更好的办法是把所有的页面都保存在一个类似钟面的环形链表中,一个表针指向最老的页面,如图3-16所示。
当发生缺页中断时,算法首先检查表针指向的页面,如果它的R位是0就淘汰该页面,并把新的页面插入这个位置,然后把表针前移一个位置,如果R位是1就清除R位并把表针前移一个位置。重复这个过程直到找到了一个R位为0的页面为止。
改进型的时钟置换算法
简单的时钟置换算法仅考虑到一个页面最近是否被访问过。事实上,如果被淘汰的页面没有被修改过,就不需要执行I/O操作写回外存。只有被淘汰的页面被修改过时,才需要写回外存。
因此,除了考虑一个页面最近有没有被访问过之外,操作系统还应考虑页面有没有被修改过。在其他条件都相同时,应优先淘汰没有修改过的页面,避免I/O操作。这就是改进型的时钟置换算法的思想。
修改位=0,表示页面没有被修改过; 修改位=1,表示页面被修改过。
为方便讨论,用(访问位,修改位)的形式表示各页面状态。如(1,1)表示一个页面近期被访问过,且被修改过。
算法规则: 将所有可能被置换的页面排成一个循环队列
第一轮: 从当前位置开始扫描到第一个(0,0) 的帧用于替换。本轮扫描不修改任何标志位。
第二轮: 若第一轮扫描失败,则重新扫描,查找第一个(0, 1)的帧用于替换。本轮将所有扫描过的帧访问位设为0。
第三轮: 若第二轮扫描失败,则重新扫描,查找第一个(0, 0)的帧用于替换。本轮扫描不修改任何标志位。
第四轮: 若第三轮扫描失败,则重新扫描,查找第一个(0, 1)的帧用于替换。
由于第二轮已将所有帧的访问位设为0,因此经过第三轮、第四轮扫描一定会有一个帧被选中,因此改进型CLOCK置换算法选择一个淘汰页面最多会进行四轮扫描。
最近最少使用页面置换算法LRU
在缺页中断发生时,置换未使用时间最长的页面。这个策略称为LRU (Least Recently Used,最近最少使用)页面置换算法。
虽然LRU在理论上是可以实现的,但代价很高。为了完全实现LRU, 需要在内存中维护一个所有页面的链表,最近最多使用的页面在表头,最近最少使用的页面在表尾。困难的是在每次访问内存时都必须要更新整个链表。在链表中找到一个页面,删除它,然后把它移动到表头是一个非常费时的操作,即使使用硬件实现也一样费时(假设有这样的硬件)。
然而,还是有一些使用特殊硬件实现LRU的方法。首先考虑一个最简单的方法,这个方法要求硬件有一个64位计数器C,它在每条指令执行完后自动加1,每个页表项必须有一个足够容纳这个计数器值的域。在每次访问内存后,将当前的C值保存到被访问页面的页表项中。一旦发生缺页中断,操作系统就检查所有页表项中计数器的值,找到值最小的一个页面,这个页面就是最近最少使用的页面。
用软件模拟LRU
内存分段
概念
内存分段(Segmentation)是将逻辑地址空间划分为多个逻辑段,每个逻辑段具有不同的大小和访问权限。每个逻辑段对应一个物理地址空间,这些物理地址空间可以是不连续的。当程序访问逻辑地址时,操作系统将其转换为相应的物理地址。
特点
利点
- 内存分段可以为不同大小的程序提供不同的内存分配。
- 内存分段可以为不同的程序提供不同的访问权限和保护。
欠点
- 内存分段可能导致内存碎片问题,需要使用一些算法来解决。
- 内存分段会增加访问内存的时间,因为需要对段地址进行转换。
段页式内存分配
段页式内存管理技术结合了内存分段和内存分页的优点,同时也具有它们各自的缺点。但是,这种技术在实践中被广泛使用,因为它提供了更好的灵活性和效率。
总的来说,内存分页、内存分段和段页式内存管理技术都是操作系统中常用的内存管理技术,它们各自具有不同的优缺点,应根据实际情况进行选择。在实际应用中,段页式内存管理技术被广泛使用,因为它可以提供更好的灵活性和效率。
地址映射
段号 | 段基址 | 段大小 | 段标志 |
---|---|---|---|
1 | 0x100000 | 8KB | 可读写 |
页表项:
页号 | 物理页号 | 页标志 |
---|---|---|
0 | 0x200 | 可读写 |
1 | 0x201 | 可读写 |
2 | 0x202 | 可读写 |
3 | 0x203 | 可读写 |
首先,将逻辑地址的段号0x12与段表中的项进行比较,发现该地址属于段1,段1的起始物理地址为0x100000,段大小为8KB,因此可以得到该段的物理地址和页表的起始地址。然后,将逻辑地址的页号0x345与页表中的项进行比较