页面置换算法详解

什么是页面置换算法?

在程序执行过程中,当访问的信息不在内存时,由操作系统负责把所需要的信息从外存调入内存,然后继续执行程序。但是有时候内存空间不够,我们这时候就需要把内存中暂时不需要的信息调出内存,换到磁盘对换区。但是具体应该换出哪个页面,就需要用到页面置换算法来确定。

页面的换入、换出需要磁盘I\O,会有较大的开销,因此好的页面置换算法应该追求更少的缺页率

什么是缺页?

要访问的页面并不在物理内存中。

最佳置换算法(OPT)

 每次选择淘汰的页面是以后永不使用 or 在最长时间内不再访问的页面。

假定系统为某进程分配了三个物理块,并考虑有以下的页面号引用串:
7,0,1,2,0,3,0,4,2,3,0,3,2,1,2,0,1,7,0,1

进程运行时,先将 7,0,1 三个页面装入内存。以后,当进程要访问页面 2 时,将会产生缺页中断。这时 OS 根据最佳置换算法,将选择页面 7 淘汰。这是因为页面 0 将作为第 5 个被访问的页面,页面 1 是第 14 个被访问的页面,而页面 7 则要在第 18 次页面访问时才需调入。下次访问页面 0 时,因它已在内存而不必产生缺页中断。当进程访问页面 3时,又将引起页面 1 被淘汰;因为,它在现有的 1,2,0 三个页面中,将是以后最晚才被访问的。下图给出了采用最佳置换算法时的置换图。由图可看出,采用最佳置换算法发生了 6 次页面置换。

注意

缺页时未必发生了页面置换,如果还有可用的空闲内存块,就不用进行页面置换。

算法优点:该算法保证了可以获得最低缺页率

算法缺点理想化的,但无法预知未来页面的使用情况,因此目前无法实现,但通常用来评价其他算法。

先进先出页面置换算法(FIFO)

每次选择淘汰的是最先进入内存的页面,也就是在内存中驻留时间最久的页面

假设系统为某进程分配了三个内存块,并考虑到有以下页面号引用串:       3,2,1,0,3,2,4,3,2,1,0,4 

当进程第一次访问页面0 时,将把第 3 页换出,因为它是最先被调入内存的;在又访问页面 3 时,又将把第 2 页换出, 因为它在现有的 2, 1, 0 三个页面中是驻留时间最久的页面。 由下图可以看出,利用 FIFO 算法时进行了 6 次页面置换,9次缺页中断。 

算法优点:实现简单

算法缺点:性能较差,先进先出算法所依据的条件是各个页面调入内存的时间,但是页面调入的先后顺序并不能保证页面使用频率和时间长短。

算法与实际进程的运行规律并不适应。Belady异常,会产生所分配的物理块数增大,页故障数不减反增的现象。只有FIFO会有,LRU和OPT不会有。

最近最久未使用算法(LRU) 

依据的原理是局部性原理。

每个页面对应的页表项中,用访问字段记录该页面从上次被访问以来所经历的时间t。当需要淘汰一个页面时,选择现有页面中t值最大的,即最近最久未使用的页面。该算法的实现需要专门的  

假设系统为某进程分配了四个内存块,并考虑到有以下页面号引用串:          1,8,1,7,8,2,7,2,1,8,3,8,2,1,3,1,7,1,3,7 

当进程第一次访问页面2时,把内存块填满,接下来依次访问7、1、8,由于内存块中有这三个页面,不产生缺页中断。接下来第一次访问页面3时,产生缺页中断,根据LRU页面置换算法,内存中现有的页面,按照距离上次被访问时间从小到大排序,依次是8、1、2、7,所以将页面7换出。

算法优点:不会出现belady现象。性能较好,接近OPT算法

算法缺点: 

1. 算法效率不高

需要对整个页表频繁的维护

LRU算法会经常用到比较,当页面数比较多的时候,会消耗大量时间在比较上

2. 实现要依托较多的硬件支持,实现所需成本较高

时钟置换算法(CLOCK) 

LRU性能接近OPT,但开销大。在此基础上,试图用比较小的开销接近LRU算法的性能。

时钟置换算法是一种性能和开销较均衡的算法,又称CLOCK算法,或最近未用算法(NRU) 

为每个页面设置一个访问位(访问位为1,表示最近访问过;访问位为0,表示最近没访问过),再将内存中的页面都通过链接指针链接成一个循环队列。当某页被访问时,其访问位置为1。当需要淘汰一个页面时,只需检查页的访问位。如果是0,就选择该页换出;如果是1,则将它置为0,暂不换出,继续检查下一个页面,若第一轮扫描中所有页面都是1,则将这些页面的访问位依次置为0后,再进行第二轮扫描,第二轮扫描中一定会有访问位为0的页面。  

简单的CLOCK算法选择一个淘汰页面最多会经过两轮扫描

改进的时钟置换算法 

简单时钟置换算法仅考虑到一个页面最近是否被访问过。如果被淘汰的页面没有被修改过,就不需要执行I/O操作写回外存。只有被淘汰的页面被修改过时,才需要写回外存。

除了一个页面最近有没有被访问过之外,OS还应考虑页面有没有被修改过。在其他条件都相同时,应优先淘汰没有修改过的页面,避免I/O操作。这就是改进的时钟置换算法的思想。修改位=0,表示页面没有被修改过;修改位=1,表示页面被修改过。

改进型CLOCK置换算法选择一个淘汰页面最多会进行四轮扫描。

时钟置换算法(改进VS简单)

改进型比简单型的优点就是减少磁盘的I\O操作次数,但为了找到可置换的页,可能要进行好多轮扫描,即算法本身的开销会有所增加。

抖动

在页面置换算法的过程中,一种最糟糕的情形是刚刚换出的页面又要换入内存,刚刚换入内存的页面又要换出,这种频繁的页面调度成为抖动或者颠簸。

原因:系统中同时运行的进程太多,分配给每个进程的物理块太少,不能满足进程正常运行的基本要求,致使每个进程在运行的过程中频繁的缺页。

工作集

进程在某段时间间隔内,要访问的页面集合。基于局部性原理,可以用最近访问过的页面集合来确定工作集。

如:

一般来说,分配给进程的物理块数(即驻留集大小)要大于工作集

  • 2
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
巡回置换问题是指在一个完全图中,每个顶点之间都有一条边,求一条经过每个顶点一次且仅一次的回路,使得回路的总长度最小。这个问题是一个NP难问题,因此通常使用启发式算法来解决。其中一种启发式算法是遗传算法。 遗传算法是一种模拟自然进化过程的优化算法。在巡回置换问题中,可以将每个可能的回路看作一个个体,通过交叉、变异等操作来产生新的个体,并通过适应度函数来评估每个个体的优劣程度。经过多代进化,最终得到一个较优的回路。 以下是巡回置换问题的遗传算法的Python实现: ```python import random # 生成初始种群 def generate_population(city_num, pop_size): population = [] for i in range(pop_size): chromosome = list(range(city_num)) random.shuffle(chromosome) population.append(chromosome) return population # 计算路径长度 def get_distance(city1, city2): return ((city1[0] - city2[0]) ** 2 + (city1[1] - city2[1]) ** 2) ** 0.5 def get_path_length(path, cities): length = 0 for i in range(len(path) - 1): length += get_distance(cities[path[i]], cities[path[i+1]]) length += get_distance(cities[path[-1]], cities[path[0]]) return length # 选择操作 def selection(population, cities): fitness_list = [1 / get_path_length(chromosome, cities) for chromosome in population] total_fitness = sum(fitness_list) probability_list = [fitness / total_fitness for fitness in fitness_list] selected_population = [] for i in range(len(population)): selected_population.append(random.choices(population, probability_list)[0]) return selected_population # 交叉操作 def crossover(parent1, parent2): child = [-1] * len(parent1) start = random.randint(0, len(parent1) - 1) end = random.randint(0, len(parent1) - 1) if start > end: start, end = end, start for i in range(start, end+1): child[i] = parent1[i] j = 0 for i in range(len(parent2)): if child[j] == -1: if parent2[i] not in child: child[j] = parent2[i] j += 1 else: j += 1 return child # 变异操作 def mutation(chromosome): index1 = random.randint(0, len(chromosome) - 1) index2 = random.randint(0, len(chromosome) - 1) chromosome[index1], chromosome[index2] = chromosome[index2], chromosome[index1] return chromosome # 遗传算法主函数 def genetic_algorithm(city_list, pop_size, generation_num, crossover_rate, mutation_rate): population = generate_population(len(city_list), pop_size) for i in range(generation_num): population = selection(population, city_list) new_population = [] for j in range(pop_size): parent1 = random.choice(population) if random.random() < crossover_rate: parent2 = random.choice(population) child = crossover(parent1, parent2) else: child = parent1 if random.random() < mutation_rate: child = mutation(child) new_population.append(child) population = new_population best_path = min(population, key=lambda x: get_path_length(x, city_list)) best_length = get_path_length(best_path, city_list) return best_path, best_length # 测试 if __name__ == '__main__': city_list = [(0, 0), (1, 1), (2, 2), (3, 3), (4, 4)] best_path, best_length = genetic_algorithm(city_list, 100, 1000, 0.8, 0.1) print('最优路径:', best_path) print('最短路径长度:', best_length) ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值