zoukankan      html  css  js  c++  java
  • (转)Linux进程调度时机

    转自:http://oss.org.cn/kernel-book/ch05/5.3.2.htm

    调度程序虽然特别重要,但它不过是一个存在于内核空间中的函数而已,并不神秘。Linux的调度程序是一个叫Schedule()的函数,这个函数被调用的频率很高,由它来决定是否要进行进程的切换,如果要切换的话,切换到哪个进程等等。我们先来看在什么情况下要执行调度程序,我们把这种情况叫做调度时机。

    Linux调度时机主要有:

    1、进程状态转换的时刻:进程终止、进程睡眠;

    2、当前进程的时间片用完时(current->counter=0);

    3、设备驱动程序

    4、进程从中断、异常及系统调用返回到用户态时;

    时机1,进程要调用sleep()或exit()等函数进行状态转换,这些函数会主动调用调度程序进行进程调度;

    时机2,由于进程的时间片是由时钟中断来更新的,因此,这种情况和时机4是一样的。

    时机3,当设备驱动程序执行长而重复的任务时,直接调用调度程序。在每次反复循环中,驱动程序都检查need_resched的值,如果必要,则调用调度程序schedule()主动放弃CPU。

    时机4,如前所述,不管是从中断、异常还是系统调用返回,最终都调用ret_from_sys_call(),由这个函数进行调度标志的检测,如果必要,则调用调用调度程序。那么,为什么从系统调用返回时要调用调度程序呢?这当然是从效率考虑。从系统调用返回意味着要离开内核态而返回到用户态,而状态的转换要花费一定的时间,因此,在返回到用户态前,系统把在内核态该处理的事全部做完。

    对 于直接执行调度程序的时机,我们不讨论,因为后面我们将会描述调度程序的工作过程。前面我们讨论了时钟中断,知道了时钟中断的重要作用,下面我们就简单看 一下每个时钟中断发生时内核要做的工作,首先对这个最频繁的调度时机有一个大体了解,然后再详细讨论调度程序的具体工作过程。

    每个时钟中断(timer interrupt)发生时,由三个函数协同工作,共同完成进程的选择和切换,它们是:schedule()、do_timer()及ret_form_sys_call()。我们先来解释一下这三个函数:

    schedule():进程调度函数,由它来完成进程的选择(调度);

    do_timer():暂且称之为时钟函数,该函数在时钟中断服务程序中被调用,是时钟中断服务程序的主要组成部分,该函数被调用的频率就是时钟中断的频率即每秒钟100次(简称100赫兹或100Hz);

    ret_from_sys_call():系统调用返回函数。当一个系统调用或中断完成时,该函数被调用,用于处理一些收尾工作,例如信号处理、核心任务等等。

    这三个函数是如何协调工作的呢?

    前面我们看到,时钟中断是一个中断服务程序,它的主要组成部分就是时钟函数do_timer(),由这个函数完成系统时间的更新、进程时间片的更新等工作,更新后的进程时间片counter作为调度的主要依据。

    在时钟中断返回时,要调用函数ret_from_sys_call(),前面我们已经讨论过这个函数,在这个函数中有如下几行:

    cmpl $0, _need_resched

    jne reschedule

         ……

    restore_all:

         RESTORE_ALL

     

    reschedule:

         call SYMBOL_NAME(schedule)   

         jmp ret_from_sys_call

     

    这几行的意思很明显:检测 need_resched 标志,如果此标志为非0,那么就转到reschedule处调用调度程序schedule()进行进程的选择。调度程序schedule()会根据具体的标准在运行队列中选择下一个应该运行的进程。当从调度程序返回时,如果发现又有调度标志被设置,则又调用调度程序,直到调度标志为0,这时,从调度程序返回时由RESTORE_ALL恢复被选定进程的环境,返回到被选定进程的用户空间,使之得到运行。

    以上就是时钟中断这个最频繁的调度时机。讨论这个的主要目的使读者对时机4有个大致的了解。

    最后要说明的是,系统调用返回函数ret_from_sys_call()是从系统调用、异常及中断返回函数通常要调用的函数,但并不是非得调用,对于那些要经常被响应的和要被尽快处理的中断请求信号,为了减少系统开销,处理完成后并不调用 ret_from_sys_call()(因为很显然的,从这些中断处理程序返回到的用户空间肯定是那个被中断的进程,无需重新选择),并且,它们作的工作要尽可能少,因为响应的频率太高了。

    Linux 调度程序和其他的UNIX调度程序不同,尤其是在“nice level”优先级的处理上,与优先权调度(priority高的进程最先运行)不同,Linux用的是时间片轮转调度(Round Robing),但同时又保证了高优先级的进程运行的既快、时间又长(both sooner and longer)。而标准的UNIX调度程序都用到了多级进程队列。大多数的实现都用到了二级优先队列:一个标准队列和一个实时(“real time”)队列。一般情况下,如果实时队列中的进程未被阻塞,它们都要在标准队列中的进程之前被执行,并且,每个队列中,“nice level”高的进程先被执行。

    总体上,Linux 调度序程在交互性方面表现很出色,当然了,这是以牺牲一部分“吞吐量”为代价的。

  • 相关阅读:
    httpcontext in asp.net unit test
    initialize or clean up your unittest within .net unit test
    Load a script file in sencha, supports both asynchronous and synchronous approaches
    classes system in sencha touch
    ASP.NET MVC got 405 error on HTTP DELETE request
    how to run demo city bars using sencha architect
    sencha touch mvc
    sencha touch json store
    sencha touch jsonp
    51Nod 1344:走格子(贪心)
  • 原文地址:https://www.cnblogs.com/yysblog/p/2766298.html
Copyright © 2011-2022 走看看