进程调度算法
先来先服务
根据到达先后顺序,考虑等待时间
非抢占式
优点:公平、简单、不会饥饿
缺点:对短进程不利
短进程优先
短进程优先得到服务,考虑运行时间
包括非抢占式和抢占式(最短剩余时间优先)
缺点:不公平,对长进程不利,可能产生饥饿
高响应比优先
根据响应比从高到低进行调度,兼顾了等待和运行时间
响应比 = (等待时间 + 要求服务时间) / 要求服务时间
非抢占式
不会饥饿
时间片轮转法
公平、轮流地为各个进程服务,让每个进程在一定时间间隔内都能得到响应
抢占式
若时间片太大会退化为先来先服务
若时间片太小会导致进程频繁切换,消耗资源
优点:公平、响应快、不会饥饿
缺点:进程切换造成开销、无法区分任务紧急程度
优先级调度
根据进程优先级从高到低进行调度
分非抢占式和抢占式(可能会导致饥饿)
多级反馈队列
设置多级就绪队列
抢占式
可能会饥饿
各级队列优先级从高到低,时间片从小到大
详见:https://www.bilibili.com/video/BV1YE411D7nH?p=17&spm_id_from=pageDriver
常用 IO 模型
一个输入操作通常包括两个阶段:
1.等待数据准备好
2.从内核向进程复制数据
对于一个套接字上的输入操作,第一步通常涉及等待数据从网络中到达
当所等待数据到达时,它被复制到内核中的某个缓冲区
第二步就是把数据从内核缓冲区复制到应用进程缓冲区
1.同步IO
调用一个功能,在功能结果未返回前,一直等待结果返回
a.阻塞式IO
调用一个函数,当调用结果返回之前,当前线程会被挂起,只有得到结果之后才会返回
使用系统调用,并一直阻塞直到内核将数据准备好,之后再由内核缓冲区复制到用户态,在等待内核准备的这段时间什么也干不了
阻塞式IO是最流行的IO模型
下图函数调用期间,一直被阻塞,直到数据准备好且从内核复制到用户程序才返回,这种IO模型为阻塞式IO
优点
简单
在阻塞等待期间,用户线程挂起,在挂起期间不会占用CPU资源
缺点
一个线程维护一个IO,不适合高并发
在并发量大的时候需要创建大量的线程来维护网络连接,内存、线程开销非常大
b.非阻塞式IO
调用一个函数,不能立刻得到结果之前,调用不能阻塞当前线程,应用进程可以继续执行,但是需要不断的执行系统调用来获知 I/O 是否完成,如果内核缓冲区有数据,内核就会把数据返回进程
内核在没有准备好数据的时候会返回错误码,而调用程序不会休眠,而是不断轮询内核数据是否准备好
下图函数调用时,如果数据没有准备好,不像阻塞式IO那样一直被阻塞,而是返回一个错误码,当数据准备好时,函数成功返回
优点
每次发起IO调用,在内核等待数据的过程中可以立即返回,用户线程不会阻塞,实时性较好。
缺点
应用进程不断轮询内核是否有数据,占用CPU资源,效率不高
一般Web服务器不会采用此模式
c.多路复用IO
类似与非阻塞,只不过轮询不是由用户线程去执行,而是由内核去轮询,内核监听程序监听到数据准备好后,调用内核函数复制数据到用户态
下图中select这个系统调用,充当代理类的角色,不断轮询注册到它这里的所有需要IO的文件描述符,有结果时,把结果告诉被代理的recvfrom函数,它本尊再亲自出马去拿数据