调度算法
进程调度算法
- 先来先服务:长作业占优势,适合CPU繁忙;不利于短作业,不适合IO繁忙
- 短作业优先:短作业占优势,适合IO繁忙,系统吞吐量高;不利于长作业,不适合CPU繁忙
- 高响应比优先:响应比=(等待时间+运行时间)/运行时间;协调长短作业,短作业运行时间短,响应比高,但长作业会因等待时间变长而提高响应比;需要计算响应比
- 时间片轮转:时间设置长对短作业不利,设置长导致上下文频繁切换,效率低。
- 最高优先级:以上算法均未考虑优先级;不利于低优先级进程,可能一直无法被调度。
- 多级反馈队列算法:用多级队列存放进程,优先级高的队列时间片短,低的队列时间片长,每个队列按照先来先服务,时间片到则放到下一优先级的队列中,有更高优先级的进程则将当前进程放回原优先级队列中,先调度高优先级进程;利于短作业,在较前面的优先级队列则已完成,利于长作业,在较低优先级队列中的时间片也较长。
页表置换算法
流程:CPU要执行1条指令,需要访问某个页面
- 若该页面在快表中,则从快表中获取并修改快表条目,如修改访问位和修改位
- 若在内存中,则读取后将该页面放进快表
- 若不在内存则需要从外存中调入,若内存已满,则需根据置换算法将某个页置换出去,接着从外存读取该页,并更新到快表中
可选择算法:
- OPT最佳页面:找到未来最久不会使用的页面置换出去,实际不可能实现,只能用来评估其他置换算法的效率
- FIFO先进先出:使用队列,效率不高,因为先进的页在最近也会被使用
- LRU最近最久未使用:将最长时间未使用的页面置换出去;实现耗时高,需要实现1个链表,表尾放着最近最久未使用的页面,表头放着最近使用的页面,每次访问内存都需要遍历链表找到访问页面位置,并将其移动到表头。
- CLOCK时钟页面:维护1个环形链表,发生缺页时遍历链表,若访问位为1则置0,若访问位为0,则将新页替换该页,实现起来较为简单,而且接近LRU的思想,访问位为0则说明已经较长时间没有被使用到,因为经历的缺页次数更多,被变0的概率更大。
- 改进CLOCK:除了考虑访问位,还考虑修改位,(访问位,修改位)表示页面状态,若页面未修改,则直接淘汰此页,不用将其写入磁盘,多进行IO操作,若访问情况相同,则优先淘汰未修改的页。
- 第一轮遍历:找(0, 0),找到则停止
- 第二轮遍历:找(0, 1),找的过程中将访问位设0,找到则停止
- 重复一二
- LFU最不常用:对每个页面维护计数器,使用时间最少的换出,同时还可以用1个计时器,每次访问时计数左移+1,一段时间后将计数器左移,让较早时间的访问无效,即频率更关注更近时间的。
磁盘调度算法
- FIFO
- 最短寻道
- SCAN
- C-SCAN
内存管理
Linux的malloc
进程的内存分配从下到上:代码区,数据区(初始化全局变量和静态变量),BSS区(未初始化全局变量和静态变量)、堆区(从低到高增长,用户手动申请),文件映射区(从高到低增长),栈区(从上到下增长,操作系统控制),内核空间。
分情况分配
- brk()
当malloc的数据小于128KB,则调用brk(),从堆区申请内存,在free时不会立即归还操作系统,而会存放在malloc的内存池中,此进程若还需要继续申请内存,则直接从内存池中获取,因为申请内存需要进行运行态的切换,这样减少CPU消耗,但同时也会导致堆区的产生很多内存碎片。 - mmap()
当malloc的数据大于128KB,则调用mmap(),从文件映射区申请内存,在free后立马归还操作系统。
free
malloc分配并不是申请要求分配的大小,而是会多申请一些空间来维护1个内存块头信息结构体,表示此次申请的空间大小,因此在free时只需要传入地址,则可根据内存卡信息来决定释放的总空间。
copy in
在用户态进行系统调用时,比如使用open(filename)打开一个文件,filename是1个char*类型,它存放在内存中,虚拟地址到物理地址的映射关系由用户的进程页表维护,因此在用户态可以直接解引用获得它的值。
但是因为发生系统调用后,进入了内核态,此时无法直接解引用,因此需要使用copyin函数,将用户态的数据复制到内核态,以在内核态中访问用户态的数据。