進程的調度與切換直接影響著進程子系統的執行效率.Linux摒棄了i386 硬體提供的進程切換方法.手動儲存進程上下文.在調度策略上,近幾個版本對其都有很大的改動.特別是在2.6.23版本與以前發布的2.6.0更是相差甚遠.在調度方面.我們以2.6.9在代碼作為基準作為分析.
一:進程切換
進程的切換過程是在context_switch()中實現的.從它的代碼說起:
static inline voidcontext_switch(struct rq *rq, struct task_struct *prev, struct task_struct *next){ struct mm_struct *mm, *oldmm; prepare_task_switch(rq, prev, next); mm = next->mm; oldmm = prev->active_mm; /* * For paravirt, this is coupled with an exit in switch_to to * combine the page table reload and the switch backend into * one hypercall. */ arch_enter_lazy_cpu_mode(); //task->mm 為空白.則是一個核心線程 if (unlikely(!mm)) { //核心線程共用上一個運行進程的mm next->active_mm = oldmm; //增加引用計數 atomic_inc(&oldmm->mm_count); enter_lazy_tlb(oldmm, next); } else //如果是使用者進程,則切換Runspace switch_mm(oldmm, mm, next); //如果上一個運行進程是核心線程 if (unlikely(!prev->mm)) { //賦active_mm為空白. prev->active_mm = NULL; //更新執行隊列的prev_mm成員 rq->prev_mm = oldmm; } /* * Since the runqueue lock will be released by the next * task (which is an invalid locking op but in the case * of the scheduler it's an obvious special-case), so we * do an early lockdep release here: */#ifndef __ARCH_WANT_UNLOCKED_CTXSW spin_release(&rq->lock.dep_map, 1, _THIS_IP_);#endif /* Here we just switch the register state and the stack. */ //切換進程的執行環境 switch_to(prev, next, prev); barrier(); /* * this_rq must be evaluated again because prev may have moved * CPUs since it called schedule(), thus the 'rq' on its stack * frame will be invalid. */ //進程切換之後的處理工作 finish_task_switch(this_rq(), prev);}