目录
一、概念的补充
首先我们要明确一个观点,进程不是占用一个CPU后就一直运行到结束的,每隔一段时间(时间片),它都会从CPU上面被剥离下来,让其他的进程上来被执行,这一过程我们可以理解为抢占。Linux内核是支持进程之间进行CPU资源抢占的,所以我们的内核又叫做基于时间片的轮转式抢占式内核。这里在给大家补充一些其他概念:
- 竞争性: 系统进程数目众多,而CPU资源只有少量,甚至1个,所以进程之间是具有竞争属性的。为了高效完成任务,更合理竞争相关资源,便具有了优先级
- 独立性: 多进程运行,需要独享各种资源,多进程运行期间互不干扰
- 并行: 多个进程在多个CPU下分别,同时进行运行,这称之为并行
- 并发: 多个进程在一个CPU下采用进程切换的方式,在一段时间之内,让多个进程都得以推进,称之为并发
二、进程切换的概念
由上面我们刚刚所说的,我们可以明确的一点是我们的进程会进行抢占,那么就肯定会有我们进程间的相互切换。那么什么是进程间的切换呢?
进程切换是指在多任务操作系统中,由于 CPU 时间片轮转或者出现中断事件,导致当前运行的进程需要被暂停,而另一个进程需要被调度并开始执行的过程。当一个进程被切换出去时,操作系统会保存该进程的上下文信息(如寄存器值、程序计数器等),然后加载另一个进程的上下文信息,使其可以继续执行。这个过程成为进程切换。
这里给大家补充一些信息:
那么我们进程切换的具体步骤是什么呢?
- 保存当前进程的上下文信息。
- 选择下一个需要执行的进程。
- 恢复所选进程的上下文信息。
- 更新内存管理单元和其他硬件资源的映射关系。
- 将 CPU 控制权交给所选进程,让其开始执行。
这里所说的进程上下文就是其在CPU中被执行时,在各个寄存器中产生的临时数据。也就是说我们在进程切换时保存的数据主要就是其在各个寄存器中产生的数据,那么其本质就是将我们寄存器的内容保存到我们的内存中。
三、Linux2.6内核进程调度队列
现在让我们来看一看进程切换具体的实例吧。
先来看看这张图,这里我们重点关注红色框框和蓝色框框部分。
我们可以发现这两个框中都各自维护了一个队列,其中一个队列叫做活跃队列,一个叫做过期队列,那么这两个队列是什么意思呢,队列里存的内容又是什么呢?
接下来我来看看为什么要维护两个队列以及他们是怎么使用的:
这里可能大家会有问题,为什么我们后来的进程不直接加入我们的活跃队列中,而是要大费苦心的去多维护一个过期队列呢?
这个想法是不错,但是会不会有一种情况,你后面来的进程优先级都很高,那就会导致我们后面优先级低的进程迟迟得不到执行,这就会导致我们上文所说的进程饥饿的问题。OS为了均衡,很明显是不可能让这种情况发生的,所以我们的OS就维护了一个过期队列,让我们后来的进程加入到过期队列中,让我们优先级低的进程也可以很好的被访问,是不是很细节。
还值得一提的是,我们的bitmap扫描队列中是否存在元素的速度是很快的,常数时间,而我们的活跃队列去找到被调度的元素也是很快的,这就是在这之中的大O(1)算法