三套算法分别是:内存分配算法,页面置换算法,和进程调度算法。之所以说三套,是因为每一类算法有多种实现。
一:内存分配算法(用于空闲内存管理),有的也叫做动态分区分配算法
这里以隐式空闲链表来举例说明:
如果我们强加一个双字对齐约束,那么块大小就总是8的倍数,且块大小的最低3位总是零,因此我们可以用最低位来指明这个块是已分配的还是空闲的。
1. 首次适配算法(first fit)
每次接到内存申请,按空闲区地址由低到高查找,找到第一个不小于分配请求的空闲块,将其分割并分配。该算法实现简单,但会在低地址部分产生许多无法利用的小空闲块(外部碎片),好处是可以在高地址部分保留大的空闲块。
2. 最佳适配算法(best fit)
需要先将空闲块按尺寸由小到大排列,每次找到最适合分配请求的空闲块。该算法用最小空间满足了要求,保留了大的空闲区,但会造成许多外部碎片。
3. 最差适配算法(worst fit)
需要先将空闲块按尺寸由大到小排列,每次找到能满足分配请求且最大的空闲块。该算法适用于请求分配的内存大小范围较窄的系统,保留了小的空闲块,减少了外部碎片的产生。
4. 下次适配算法(next fit)
首次适配算法的改进版,每次找到合适的空闲区后记录当时的位置,以便在下次寻找空闲区时从上次结束的地方开始搜索,而不是像首次适配算法那样每次都从头开始。实际性能略低于首次适配算法。
5. 快速适配算法(quick fit)
为那些常用大小的空闲区维护单独的链表,在寻找一个指定大小的空闲区时十分快速,但寻找相邻块合并的过程非常费时。
二:页面置换算法(用在虚拟内存中缺页中断时)
1. 最优页面置换算法
每次淘汰掉最长时间后才会用到的页面,因为无法预知哪些页面最长时间后才会用到,所以该算法只是理论上的,无法实现。但可以用来与其他可实现算法做性能对比。
2. 先进先出页面置换算法(FIFO)
每次淘汰掉最早进入内存的页面。该算法实现简单,但性能不高,因为最早进入的页面不代表最不常使用。
3. 第二次机会页面置换算法
改进版的FIFO算法,使用了访问位,每次淘汰掉最早进入且访问位为0的页面。
4. 最近未使用页面置换算法(NRU)
每次淘汰掉最近一个时钟滴答中没有被访问的页面,且定期清0所有页面的访问位,以区别最近没有被访问的页面和被访问的页面。
5. 最近最少使用页面置换算法(LRU)
每次淘汰掉最长时间没有访问过的页面,该算法理论上可以实现,但代价太高,因为每次访问内存都必须要更新整个链表。所以一般用微调后的NFU算法(老化算法)来模拟LRU算法。
6. 时钟置换算法
将所有页面保存在环形链表中,发生缺页中断时,首先检查指针指向的页面,若该页面访问位为0则淘汰,否则将访问位置0后指针前移一个位置,重复这个过程直到找到一个访问位为0的页面为止。
7. 工作集页面置换算法
原理类似滑动窗口,先指定一个工作集窗口,还需要额外维护一个在工作集窗口内的所有页面的集合,每当发生缺页中断时,淘汰一个不在工作集中的页面。
三:进程调度算法(用在多个进程同时竞争CPU时)
1. 先来先服务(FCFS)
非抢占式,按照进程请求CPU的顺序使用CPU,该算法实现简单,但平均等待时间波动较大,不公平。
2. 最短作业优先
非抢占式,优先执行最短的作业,需要预估作业运行所需时间,且有可能导致长作业饥饿。
3. 最短剩余时间优先
最短作业优先的抢占式版本,调度程序总是选择剩余运行时间最短的那个进程运行。
4. 轮转调度(Round Robin)
每个进程被分配一个时间片,时间片用完就剥夺该进程的CPU并分配给另一个进程,该算法的关键在于选择一个适合的时间片长度。如果太长,可能会退化成FCFS,太短又会导致上下文切换开销过大。根据经验,上下文切换开销最好处于1%以内。
5. 多级反馈队列
每一个队列都是一个轮转调度,且越往下时间片越大,一个进程可以在不同的队列中移动。当一个进程用完分配的时间片后,它将被移到下一个队列中。
6. 优先级调度
为每个进程分配一个优先级,按优先级顺序进行调度,同时为了防止低优先级的进程永远得不到调度,可以随着时间的推移增加等待进程的优先级。
注
以上提到的只是常用的算法,还有一些偏冷门的算法没有列出。感觉每套 能记住三四个算法就足够应付面试了,此处针对每种算法只进行了简单描述,做备忘之用,若要知晓其细节,还请参考经典的操作系统书籍,如《现代操作系统》,《深入理解计算机系统》等。
点赞,收藏