Linux 核心--5.Linux进程( 四 )


核心在几个位置调用调度管理器 。如当前进程被放入等待队列后运行或者系统调用结束时 , 以及从系统模式返回用户模式时 。此时系统时钟将当前进程的counter值设为0以驱动调度管理器 。每次调度管理器运行时将进行下列操作:


kernel work
调度管理器运行底层处理程序并处理调度任务队列 。kernel一章将详细描叙这个轻量级核心线程 。
Current process
当选定其他进程运行之前必须对当前进程进行一些处理 。
如果当前进程的调度策略是时间片轮转 , 则它被放回到运行队列 。


如果任务可中断且从上次被调度后接收到了一个信号 , 则它的状态变为Running 。


如果当前进程超时 , 则它的状态变为Running 。


如果当前进程的状态是Running , 则状态保持不变 。那些既不处于Running状态又不是可中断的进程将会从运行队列中删除 。这意味着调度管理器选择运行进程时不会将这些进程考虑在内 。



Process selection
调度器在运行队列中选择一个最迫切需要运行的进程 。如果运行队列中存在实时进程(那些具有实时调度策略的进程) , 则它们比普通进程更多的优先级权值 。普通进程的权值是它的counter值 , 而实时 进程则是counter加上1000 。这表明如果系统中存在可运行的实时进程 , 它们将总是在任何普通进程之前运行 。如果系统中存在和当前进程相同优先级的其它进程 , 这时当前运行进程已经用掉了一些时间片 , 所以它将处在不利形势(其counter已经变小);而原来优先级与它相同的进程的counter值显然比它大 , 这样位于运行队列中最前面的进程将开始执行而当前进程被放回到运行队列中 。在存在多个相同优先级进程的平衡系统中 , 每个进程被依次执行 , 这就是Round Robin策略 。然而由于进程经常需要等待某些资源 , 所以它们的运行顺序也常发变化 。
Swap processes
如果系统选择其他进程运行 , 则必须被挂起当前进程且开始执行新进程 。进程执行时将使用寄存器、物理内存以及CPU 。每次调用子程序时 , 它将参数放在寄存器中并把返回地址放置在堆栈中 , 所以调度管理器总是运行在当前进程的上下文 。虽然可能在特权模式或者核心模式中 , 但是仍然处于当前运行进程中 。当挂起进程的执行时 , 系统的机器状态 , 包括程序计数器(PC)和全部的处理器寄存器 , 必须存储在进程的task_struct数据结构中 。同时加载新进程的机器状态 。这个过程与系统类型相关 , 不同的CPU使用不同的方法完成这个工作 , 通常这个操作需要硬件辅助完成 。


进程的切换发生在调度管理器运行之后 。以前进程保存的上下文与当前进程加载时的上下文相同 , 包括进程程序计数器和寄存器内容 。

如果以前或者当前进程使用了虚拟内存 , 则系统必须更新其页表入口 , 这与具体体系结构有关 。如果处理器使用了转换旁视缓冲或者缓冲了页表入口(如Alpha AXP) , 那么必须冲刷以前运行进程的页表入口 。

4.3.1多处理器系统中的调度
在Linux世界中 , 多CPU系统非常少见 。但是Linux上已经做了很多工作来保证它能运行在SMP(对称多处理)机器上 。Linux能够在系统中的CPU间进行合理的负载平衡调度 。这里的负载平衡工作比调度管理器所做的更加明显 。

在多处理器系统中 , 人们希望每个处理器总处与工作状态 。当处理器上的当前进程用完它的时间片或者等待系统资源时 , 各个处理器将独立运行调度管理器 。SMP系统中一个值得注意的问题是系统中不止一个idle进程 。在单处理器系统中 , idle进程是task数组中的第一个任务 , 在SMP系统中每个CPU有一个idle进程 , 同时每个CPU都有一个当前进程 , SMP系统必须跟踪每个处理器中的idle进程和当前进程 。

推荐阅读