Linux的调度程序是一个叫Schedule的函数,由它来决定是否要进行进程的切换。
而所谓的调度时机则是在什么情况下执行调度程序?
1、进程状态转换的时刻进程终止、进程睡眠
2、当前进程的时间片用完时(current-counter0)
3、设备驱动程序执行长而重复的任务时
4、进程从中断、异常及系统调用返回到用户态时
时机1进程要调用sleep或exit等函数进行状态转换,这些函数会主动调用调度程序进行进程调度
时机2由于进程的时间片是由时钟中断来更新的,因此这种情况和时机4是一样的。
时机3当设备驱动程序执行长而重复的任务时直接调用调度程序。在每次反复循环中驱动程序都检查need_resched的
值,如果必要则调用调度程序schedule主动放弃CPU。
时机4如前所述不管是从中断、异常还是系统调用返回,最终都调用ret_from_sys_call由这个函数进行调度标志的检
测,如果必要,则调用调度程序。
那么为什么从系统调用返回时要调用调度程序呢?
这当然是从效率考虑。
从系统调用返回意味着要离开内核态而返回到用户态,而状态的转换要花费一定的时间,因此在返回到用户态前系统把在内核态该处理的事全部做完。
下面简单看一下每个时钟中断发生时内核要做的工作:
每个时钟中断(timerinterrupt)发生时,由三个函数协同工作,共同完成进程的选择和切换。
它们是schedule、do_timer及ret_form_sys_call。
schedule:进程调度函数。由它来完成进程的选择调度
do_timer:暂且称之为时钟函数。该函数在时钟中断服务程序中被调用,是时钟中断服务程序的主要组成部分。该函数
被调用的频率就是时钟中断的频率,即每秒钟100次简称100赫兹或100Hz
ret_from_sys_call:系统调用返回函数。当一个系统调用或中断完成时,该函数被调用。用于处理一些收尾工作。例
如信号处理、核心任务等等。
这三个函数是如何协调工作的呢?
例:时钟中断(最频繁的调度时机)
1、时钟中断是一个中断服务程序,它的主要组成部分就是时钟函数do_timer。由这个函数完成系统时间的更新、进程时间片的更新等工作。更新后的进程时间片counter作为调度的主要依据。
2、在时钟中断返回时要调用函数ret_from_sys_call,在这个函数中need_resched标志如果此标志为非0,那么就转到reschedule处调用调度程序(schedule)进行进程的选择。调度程序(schedule)会根据具体的标准在运行队列中选择下一个应该运行的进程。
3、当从调度程序返回时,如果发现又有调度标志被设置,则又调用调度程序直到调度标志为0。这时从调度程序返回时由RESTORE_ALL恢复被选定进程的环境,返回到被选定进程的用户空间使之得到运行。
系统调用返回函数(ret_from_sys_call)是从系统调用、异常及中断返回函数通常要调用的函数,但并不是非得调用。对于那些要经常被响应的和要被尽快处理的中断请求信号,为了减少系统开销,处理完成后并不调用ret_from_sys_call因为很显然的从这些中断处理程序返回到的用户空间肯定是那个被中断的进程,无需重新选择,并且它们做的工作要尽可能少,因为响应的频率太高了。
Linux调度程序和其他的UNIX调度程序不同。尤其是在nicelevel优先级的处理上,与优先权调度priority高的进程最先运行不同。Linux用的是时间片轮转调度(RoundRobing),但同时又保证了高优先级的进程运行的既快、时间又长(bothsooner and longer)。
而标准的UNIX调度程序都用到了多级进程队列。大多数的实现都用到了二级优先队列一个标准队列和一个实时realtime队列。一般情况下如果实时队列中的进程未被阻塞,它们都要在标准队列中的进程之前被执行并且每个队列中nicelevel高的进程先被执行。
总体上Linux调度序程在交互性方面表现很出色当然了这是以牺牲一部分吞吐量为代价的。
Linux调度程序分类:
->长期调度程序(作业调度程序)控制多道程序设计的程度(内存中进程的数量)
->中期调度程序:用于交换 即将进程从内存(或CPU竞争)中移出,从而降低多道程序设计程度。而后进程被重新装入内存,并从中断处继续执行。
->短期调度程序(CPU调度程序)频繁的为CPU选择新进程
进程需要搭配合理,即CPU为主和I/O为主的进程数量协调,即不使CPU空闲,又不使I/O无事可做。