进程切换有两个任务要实现:
- 内核必须决定何时进行调度, 由此会有两个问题: 每个进程分配多长时间, 哪一个进程是调度的下一个进程
- 内核从进程A切换到进程B时, 必须确保进程B的执行环境与上一次撤销其处理器资源时完全相同
当内核选择要切换到的新进程之后, 下一步进行上下文切换, 这一步的工作主要由context_switch函数完成.
/* kernel/sched.c */
asmlinkage void __sched schedule(void)
{
// .... 找到被调度进程
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);
barrier();
finish_task_switch(prev);
} else
spin_unlock_irq(&rq->lock);
// ...
}
static inline
task_t * context_switch(runqueue_t *rq, task_t *prev, task_t *next)
{
struct mm_struct *mm = next->mm;
struct mm_struct *oldmm = prev->active_mm;
if (unlikely(!mm)) {
next->active_mm = oldmm;
atomic_inc(&oldmm->mm_count);
enter_lazy_tlb(oldmm, next);
} else
switch_mm(oldmm, mm, next);
if (unlikely(!prev->mm)) {
prev->active_mm = NULL;
WARN_ON(rq->prev_mm);
rq->prev_mm = oldmm;
}
/* Here we just switch the register state and the stack. */
switch_to(prev, next, prev);
return prev;
}