74.html
来自「linux 0.11中文版 有注释」· HTML 代码 · 共 632 行 · 第 1/4 页
HTML
632 行
<a name='L120'> <font color='red'>}</font>
<a name='L121'> <b>else</b>
<a name='L122'> <font color='red'>{</font> <i><font color='green'>// 否则的话说明是第一次使用,</font></i>
<a name='L123'> <b>__asm__</b> ("fninit"::); <i><font color='green'>// 于是就向协处理器发初始化命令,</font></i>
<a name='L124'> current->used_math = 1; <i><font color='green'>// 并设置使用了协处理器标志。</font></i>
<a name='L125'> <font color='red'>}</font>
<a name='L126'><font color='red'>}</font>
<a name='L127'>
<a name='L128'><i><font color='green'>/*</font></i>
<a name='L129'><i><font color='green'> * 'schedule()' is the scheduler function. This is GOOD CODE! There</font></i>
<a name='L130'><i><font color='green'> * probably won't be any reason to change this, as it should work well</font></i>
<a name='L131'><i><font color='green'> * in all circumstances (ie gives IO-bound processes good response etc).</font></i>
<a name='L132'><i><font color='green'> * The one thing you might take a look at is the signal-handler code here.</font></i>
<a name='L133'><i><font color='green'> *</font></i>
<a name='L134'><i><font color='green'> * NOTE!! Task 0 is the 'idle' task, which gets called when no other</font></i>
<a name='L135'><i><font color='green'> * tasks can run. It can not be killed, and it cannot sleep. The 'state'</font></i>
<a name='L136'><i><font color='green'> * information in task[0] is never used.</font></i>
<a name='L137'><i><font color='green'> */</font></i>
<a name='L138'><i><font color='green'>/*</font></i>
<a name='L139'><i><font color='green'> * 'schedule()'是调度函数。这是个很好的代码!没有任何理由对它进行修改,因为它可以在所有的</font></i>
<a name='L140'><i><font color='green'> * 环境下工作(比如能够对IO-边界处理很好的响应等)。只有一件事值得留意,那就是这里的信号</font></i>
<a name='L141'><i><font color='green'> * 处理代码。</font></i>
<a name='L142'><i><font color='green'> * 注意!!任务0 是个闲置('idle')任务,只有当没有其它任务可以运行时才调用它。它不能被杀</font></i>
<a name='L143'><i><font color='green'> * 死,也不能睡眠。任务0 中的状态信息'state'是从来不用的。</font></i>
<a name='L144'><i><font color='green'> */</font></i>
<a name='L145'><b>void</b>
<a name='L146'><a href='../R/586.html' title='Multiple refered from 9 places.'>schedule</a> (<b>void</b>)
<a name='L147'><font color='red'>{</font>
<a name='L148'> <b>int</b> <a href='../D/839.html' title='Multiple defined in 4 places.'>i</a>, next, c;
<a name='L149'> <b>struct</b> task_struct **p; <i><font color='green'>// 任务结构指针的指针。</font></i>
<a name='L150'>
<a name='L151'> <i><font color='green'>/* check alarm, wake up any interruptible tasks that have got a signal */</font></i>
<a name='L152'> <i><font color='green'>/* 检测alarm(进程的报警定时值),唤醒任何已得到信号的可中断任务 */</font></i>
<a name='L153'>
<a name='L154'> <i><font color='green'>// 从任务数组中最后一个任务开始检测alarm。</font></i>
<a name='L155'> <b>for</b> (p = &<a href='../S/36.html#L8' title='Defined at 8 in include/linux/sched.h.'>LAST_TASK</a>; p > &<a href='../S/36.html#L7' title='Defined at 7 in include/linux/sched.h.'>FIRST_TASK</a>; --p)
<a name='L156'> <b>if</b> (*p)
<a name='L157'> <font color='red'>{</font>
<a name='L158'> <i><font color='green'>// 如果任务的alarm 时间已经过期(alarm<jiffies),则在信号位图中置SIGALRM 信号,然后清alarm。</font></i>
<a name='L159'> <i><font color='green'>// jiffies 是系统从开机开始算起的滴答数(10ms/滴答)。定义在sched.h 第139 行。</font></i>
<a name='L160'> <b>if</b> ((*p)->alarm && (*p)->alarm < jiffies)
<a name='L161'> <font color='red'>{</font>
<a name='L162'> (*p)->signal |= (1 << (<a href='../S/39.html#L27' title='Defined at 27 in include/signal.h.'>SIGALRM</a> - 1));
<a name='L163'> (*p)->alarm = 0;
<a name='L164'> <font color='red'>}</font>
<a name='L165'> <i><font color='green'>// 如果信号位图中除被阻塞的信号外还有其它信号,并且任务处于可中断状态,则置任务为就绪状态。</font></i>
<a name='L166'> <i><font color='green'>// 其中'~(_BLOCKABLE & (*p)->blocked)'用于忽略被阻塞的信号,但SIGKILL 和SIGSTOP 不能被阻塞。</font></i>
<a name='L167'> <b>if</b> (((*p)->signal & ~(<a href='../S/74.html#L31' title='Defined at 31 in kernel/sched.c.'>_BLOCKABLE</a> & (*p)->blocked)) &&
<a name='L168'> (*p)->state == <a href='../S/36.html#L21' title='Defined at 21 in include/linux/sched.h.'>TASK_INTERRUPTIBLE</a>)
<a name='L169'> (*p)->state = <a href='../S/36.html#L20' title='Defined at 20 in include/linux/sched.h.'>TASK_RUNNING</a>; <i><font color='green'>//置为就绪(可执行)状态。</font></i>
<a name='L170'> <font color='red'>}</font>
<a name='L171'>
<a name='L172'> <i><font color='green'>/* this is the scheduler proper: */</font></i>
<a name='L173'> <i><font color='green'>/* 这里是调度程序的主要部分 */</font></i>
<a name='L174'>
<a name='L175'> <b>while</b> (1)
<a name='L176'> <font color='red'>{</font>
<a name='L177'> c = -1;
<a name='L178'> next = 0;
<a name='L179'> <a href='../D/839.html' title='Multiple defined in 4 places.'>i</a> = <a href='../S/36.html#L4' title='Defined at 4 in include/linux/sched.h.'>NR_TASKS</a>;
<a name='L180'> p = &task[<a href='../S/36.html#L4' title='Defined at 4 in include/linux/sched.h.'>NR_TASKS</a>];
<a name='L181'> <i><font color='green'>// 这段代码也是从任务数组的最后一个任务开始循环处理,并跳过不含任务的数组槽。比较每个就绪</font></i>
<a name='L182'> <i><font color='green'>// 状态任务的counter(任务运行时间的递减滴答计数)值,哪一个值大,运行时间还不长,next 就</font></i>
<a name='L183'> <i><font color='green'>// 指向哪个的任务号。</font></i>
<a name='L184'> <b>while</b> (--<a href='../D/839.html' title='Multiple defined in 4 places.'>i</a>)
<a name='L185'> <font color='red'>{</font>
<a name='L186'> <b>if</b> (!*--p)
<a name='L187'> <b>continue</b>;
<a name='L188'> <b>if</b> ((*p)->state == <a href='../S/36.html#L20' title='Defined at 20 in include/linux/sched.h.'>TASK_RUNNING</a> && (*p)->counter > c)
<a name='L189'> c = (*p)->counter, next = <a href='../D/839.html' title='Multiple defined in 4 places.'>i</a>;
<a name='L190'> <font color='red'>}</font>
<a name='L191'> <i><font color='green'>// 如果比较得出有counter 值大于0 的结果,则退出124 行开始的循环,执行任务切换(141 行)。</font></i>
<a name='L192'> <b>if</b> (c)
<a name='L193'> <b>break</b>;
<a name='L194'> <i><font color='green'>// 否则就根据每个任务的优先权值,更新每一个任务的counter 值,然后回到125 行重新比较。</font></i>
<a name='L195'> <i><font color='green'>// counter 值的计算方式为counter = counter /2 + priority。[右边counter=0??]</font></i>
<a name='L196'> <b>for</b> (p = &<a href='../S/36.html#L8' title='Defined at 8 in include/linux/sched.h.'>LAST_TASK</a>; p > &<a href='../S/36.html#L7' title='Defined at 7 in include/linux/sched.h.'>FIRST_TASK</a>; --p)
<a name='L197'> <b>if</b> (*p)
<a name='L198'> (*p)->counter = ((*p)->counter >> 1) + (*p)->priority;
<a name='L199'> <font color='red'>}</font>
<a name='L200'> <a href='../S/36.html#L288' title='Defined at 288 in include/linux/sched.h.'>switch_to</a> (next); <i><font color='green'>// 切换到任务号为next 的任务,并运行之。</font></i>
<a name='L201'><font color='red'>}</font>
<a name='L202'>
<a name='L203'><i><font color='green'>//// pause()系统调用。转换当前任务的状态为可中断的等待状态,并重新调度。</font></i>
<a name='L204'><i><font color='green'>// 该系统调用将导致进程进入睡眠状态,直到收到一个信号。该信号用于终止进程或者使进程调用</font></i>
<a name='L205'><i><font color='green'>// 一个信号捕获函数。只有当捕获了一个信号,并且信号捕获处理函数返回,pause()才会返回。</font></i>
<a name='L206'><i><font color='green'>// 此时pause()返回值应该是-1,并且errno 被置为EINTR。这里还没有完全实现(直到0.95 版)。</font></i>
<a name='L207'><b>int</b>
<a name='L208'><a href='../R/664.html' title='Multiple refered from 3 places.'>sys_pause</a> (<b>void</b>)
<a name='L209'><font color='red'>{</font>
<a name='L210'> current->state = <a href='../S/36.html#L21' title='Defined at 21 in include/linux/sched.h.'>TASK_INTERRUPTIBLE</a>;
<a name='L211'> <a href='../S/74.html#L146' title='Defined at 146 in kernel/sched.c.'>schedule</a> ();
<a name='L212'> <b>return</b> 0;
<a name='L213'><font color='red'>}</font>
<a name='L214'>
<a name='L215'><i><font color='green'>// 把当前任务置为不可中断的等待状态,并让睡眠队列头的指针指向当前任务。</font></i>
<a name='L216'><i><font color='green'>// 只有明确地唤醒时才会返回。该函数提供了进程与中断处理程序之间的同步机制。</font></i>
<a name='L217'><i><font color='green'>// 函数参数*p 是放置等待任务的队列头指针。(参见列表后的说明)。</font></i>
<a name='L218'><b>void</b>
<a name='L219'><a href='../R/615.html' title='Multiple refered from 12 places.'>sleep_on</a> (<b>struct</b> task_struct **p)
<a name='L220'><font color='red'>{</font>
<a name='L221'> <b>struct</b> task_struct *tmp;
<a name='L222'>
<a name='L223'> <i><font color='green'>// 若指针无效,则退出。(指针所指的对象可以是NULL,但指针本身不会为0)。</font></i>
<a name='L224'> <b>if</b> (!p)
<a name='L225'> <b>return</b>;
<a name='L226'> <b>if</b> (current == &(init_task.task)) <i><font color='green'>// 如果当前任务是任务0,则死机(impossible!)。</font></i>
<a name='L227'> <a href='../S/72.html#L24' title='Defined at 24 in kernel/panic.c.'>panic</a> ("task[0] trying to sleep");
<a name='L228'> tmp = *p; <i><font color='green'>// 让tmp 指向已经在等待队列上的任务(如果有的话)。</font></i>
<a name='L229'> *p = current; <i><font color='green'>// 将睡眠队列头的等待指针指向当前任务。</font></i>
<a name='L230'> current->state = <a href='../S/36.html#L22' title='Defined at 22 in include/linux/sched.h.'>TASK_UNINTERRUPTIBLE</a>; <i><font color='green'>// 将当前任务置为不可中断的等待状态。</font></i>
<a name='L231'> <a href='../S/74.html#L146' title='Defined at 146 in kernel/sched.c.'>schedule</a> (); <i><font color='green'>// 重新调度。</font></i>
<a name='L232'> <i><font color='green'>// 只有当这个等待任务被唤醒时,调度程序才又返回到这里,则表示进程已被明确地唤醒。</font></i>
<a name='L233'> <i><font color='green'>// 既然大家都在等待同样的资源,那么在资源可用时,就有必要唤醒所有等待该资源的进程。该函数</font></i>
<a name='L234'> <i><font color='green'>// 嵌套调用,也会嵌套唤醒所有等待该资源的进程。然后系统会根据这些进程的优先条件,重新调度</font></i>
<a name='L235'> <i><font color='green'>// 应该由哪个进程首先使用资源。也即让这些进程竞争上岗。</font></i>
<a name='L236'> <b>if</b> (tmp) <i><font color='green'>// 若还存在等待的任务,则也将其置为就绪状态(唤醒)。</font></i>
<a name='L237'> tmp->state = 0;
<a name='L238'><font color='red'>}</font>
<a name='L239'>
<a name='L240'><i><font color='green'>// 将当前任务置为可中断的等待状态,并放入*p 指定的等待队列中。参见列表后对sleep_on()的说明。</font></i>
<a name='L241'><b>void</b>
<a name='L242'><a href='../R/507.html' title='Multiple refered from 4 places.'>interruptible_sleep_on</a> (<b>struct</b> task_struct **p)
<a name='L243'><font color='red'>{</font>
<a name='L244'> <b>struct</b> task_struct *tmp;
<a name='L245'>
<a name='L246'> <b>if</b> (!p)
<a name='L247'> <b>return</b>;
<a name='L248'> <b>if</b> (current == &(init_task.task))
<a name='L249'> <a href='../S/72.html#L24' title='Defined at 24 in kernel/panic.c.'>panic</a> ("task[0] trying to sleep");
<a name='L250'> tmp = *p;
<a name='L251'> *p = current;
<a name='L252'>repeat:current->state = <a href='../S/36.html#L21' title='Defined at 21 in include/linux/sched.h.'>TASK_INTERRUPTIBLE</a>;
<a name='L253'> <a href='../S/74.html#L146' title='Defined at 146 in kernel/sched.c.'>schedule</a> ();
<a name='L254'> <i><font color='green'>// 如果等待队列中还有等待任务,并且队列头指针所指向的任务不是当前任务时,则将该等待任务置为</font></i>
<a name='L255'> <i><font color='green'>// 可运行的就绪状态,并重新执行调度程序。当指针*p 所指向的不是当前任务时,表示在当前任务被放</font></i>
<a name='L256'> <i><font color='green'>// 入队列后,又有新的任务被插入等待队列中,因此,既然本任务是可中断的,就应该首先执行所有</font></i>
<a name='L257'> <i><font color='green'>// 其它的等待任务。</font></i>
<a name='L258'> <b>if</b> (*p && *p != current)
<a name='L259'> <font color='red'>{</font>
<a name='L260'> (**p).state = 0;
<a name='L261'> <b>goto</b> repeat;
<a name='L262'> <font color='red'>}</font>
<a name='L263'> <i><font color='green'>// 下面一句代码有误,应该是*p = tmp,让队列头指针指向其余等待任务,否则在当前任务之前插入</font></i>
<a name='L264'> <i><font color='green'>// 等待队列的任务均被抹掉了。参见图4.3。</font></i>
<a name='L265'> *p = <a href='../D/261.html' title='Multiple defined in 12 places.'>NULL</a>;
<a name='L266'> <b>if</b> (tmp)
<a name='L267'> tmp->state = 0;
<a name='L268'><font color='red'>}</font>
<a name='L269'>
<a name='L270'><i><font color='green'>// 唤醒指定任务*p。</font></i>
<a name='L271'><b>void</b>
<a name='L272'><a href='../R/733.html' title='Multiple refered from 16 places.'>wake_up</a> (<b>struct</b> task_struct **p)
<a name='L273'><font color='red'>{</font>
<a name='L274'> <b>if</b> (p && *p)
<a name='L275'> <font color='red'>{</font>
<a name='L276'> (**p).state = 0; <i><font color='green'>// 置为就绪(可运行)状态。</font></i>
<a name='L277'> *p = <a href='../D/261.html' title='Multiple defined in 12 places.'>NULL</a>;
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?