进程调度——schedule()(二)

来源:互联网 发布:罗京 艾滋 知乎 编辑:程序博客网 时间:2024/05/17 02:10
1.2 完成进程切换时所执行的操作

找到next进程之后,就是要将该进程投入运行了。此时schedule()函数将进行如下操作:

(1)首先内核会立即访问next进程的thread_info数据结构,其地址存放在next进程描述符的接近顶部的位置。

prefetch(next);
prefetch宏提示CPU控制单元把next的进程描述符第一部分字段的内容装入高速缓存。

(2)在替代prev之前,调度程序应该完成一些管理工作:

clear_tsk_need_resched(prev);rcu_qsctr_inc(task_cpu(prev));
为了防止schedule()函数以延迟方式被调用,调用clear_tsk_need_resched()函数来清除prev的TIF_NEED_RESCHED标志。然后,函数记录CPU正在经历静止状态(quiescent state)。

之后还要必须减少prev的平均睡眠时间,并把它补充给进程所使用的CPU时间片:

prev->sleep_avg -= run_time;if ((long)prev->sleep_avg <= 0)prev->sleep_avg = 0;prev->timestamp = prev->last_ran = now;
随后更新进程的时间戳。

(3)检查next与prev是不是同一个进程。如果是,就不做进程切换;否者就要进行进程切换。

if (likely(prev != next)) {next->timestamp = now;rq->nr_switches++;rq->curr = next;++*switch_count;prepare_arch_switch(rq, next);prev = context_switch(rq, prev, next);} elsespin_unlock_irq(&rq->lock);
其中,context_switch()函数建立next的地址空间。

这样,进程切换就完成了,不过还需要进行其他操作来最后完成进程切换。
1.3进程切换之后执行的操作

schedule()函数中在switch_to宏调用之后紧接着的指令并不由next进程立即执行,而是稍后当调度程序又选择prev执行时又prev执行。然而,在那个时刻,prev局部变量并不指向我们开始描述schedule()时所替换出去的原来那个进程,而是指向prev被调度时由prev替换出的原来那个进程(注意在进程切换时涉及三个进程)。进程切换之后执行的指令为:

barrier();finish_task_switch(prev);
宏barrier()产生一个代码优化屏障。finish_task_switch()函数负责释放运动队列的自旋锁并打开本地中断等工作。
最后,schedule()函数在需要时重新获得大内核锁,重新启动内核抢占,并检查是否一些其他的进程已经设置了当前进程的TIF_NEED_RESCHED标志。如果是,则整个schedule()函数重新开始执行,否则,函数结束。




原创粉丝点击