linux進程管理 – 核心調度器

來源:互聯網
上載者:User
1966     /* Here we just switch the register state and the stack. */1967     switch_to(prev, next, prev);1968 1969     barrier();

linux核心進程調度器基於兩個函數:周期性調度器函數和主調度器函數.

周期性調度器

所謂周期性調度器就是scheduler_tick中實現。如果系統正在活動中,核心會按照HZ自動調用這個函數。實際上在每個滴答的handler中會調用這個函數。如果在沒有進程等待調度,那麼在電腦電力供應不足的情況下,也可以關閉該調度器以減少電能消耗。該函數會啟用負責當前進程的調度類的周期性調度方法。

        if (curr != rq->idle) /* FIXME: needed? */                curr->sched_class->task_tick(rq, curr);

由於調度器的模組化結構,調度器本身實現比較簡單,因為主要的工作完全可以委託給特定調度器類的方法。

task_tick的實現完全依賴於底層的調度器類。例如,CFS調度器類會在方法中檢測進程是否已經運行太長時間,以避免過長的延遲。如果需要調度,那麼會調用set_tsk_need_resched函數來設定TIF_NEED_RESCHED標誌,以表示該請求。

主調度器

在核心的許多地方,如果需要將CPU分配給與當前活動進程不同的另一個進程,都會直接調用主調度器函數schedule。在從系統調用返回後,核心會檢查當前進程是否設定了重新調度標誌TIF_NEED_RESCHED標誌(例如上面提到的 scheduler_tick就可能會設定這個標誌),如果設定了,則調用schedule函數。

我們現在看一下schedule的實現

3616 /*3617  * schedule() is the main scheduler function.3618  */3619 asmlinkage void __sched schedule(void)3620 {3621         struct task_struct *prev, *next;3622         long *switch_count;3623         struct rq *rq;3624         int cpu;3625 3626 need_resched:3627         preempt_disable();3628         cpu = smp_processor_id();3629         rq = cpu_rq(cpu);3630         rcu_qsctr_inc(cpu);3631         prev = rq->curr;3632         switch_count = &prev->nivcsw;

3630 先獲得當前正在啟動並執行進程,儲存在prev中。

3639         /*3640          * Do the rq-clock update outside the rq lock:3641          */3642         local_irq_disable();3643         __update_rq_clock(rq);3644         spin_lock(&rq->lock);3645         clear_tsk_need_resched(prev);

3643 更新rq->prev_clock_raw和rq->clock

3645 清除TIF_NEED_SCHED標誌

3647         if (prev->state && !(preempt_count() & PREEMPT_ACTIVE)) {3648                 if (unlikely((prev->state & TASK_INTERRUPTIBLE) &&3649                                 unlikely(signal_pending(prev)))) {3650                         prev->state = TASK_RUNNING;3651                 } else {3652                         deactivate_task(rq, prev, 1);3653                 }3654                 switch_count = &prev->nvcsw;3655         }

如果當前進程處在可中斷睡眠狀態,那麼必須再次提升為運行進程。否則調用deactivate_task使得進程停止活動

3660         prev->sched_class->put_prev_task(rq, prev);3661         next = pick_next_task(rq, prev);

調用調度器類的put_prev_task通知調度器類當前的進程要被另外一個進程取代。這個操作並不意味著prev從就緒隊列移除,而是提供了一個時機,執行一些記賬工作。

pick_next_task選擇下一個應該執行的進程。注意新選擇的進程有可能就是原來的進程,比如就緒隊列中僅有一個進程的情況。

3665         if (likely(prev != next)) {3666                 rq->nr_switches++;3667                 rq->curr = next;3668                 ++*switch_count;3669 3670                 context_switch(rq, prev, next); /* unlocks the rq */3671         } else3672                 spin_unlock_irq(&rq->lock);

如果新進程不等於舊的進程,那麼我們調用context_switch進行進程內容相關的切換。

環境切換

1929 static inline void1930 context_switch(struct rq *rq, struct task_struct *prev,1931            struct task_struct *next)1932 {...............          1945     if (unlikely(!mm)) {1946         next->active_mm = oldmm;1947         atomic_inc(&oldmm->mm_count);1948         enter_lazy_tlb(oldmm, next);1949     } else1950         switch_mm(oldmm, mm, next);

switch_mm是一個體繫結構特定的函數,前換頁全域目錄以安裝一個新的地址空間。對於arm平台來說,就是設定CP15副處理器TTB寄存器為新的pgd;對於X86來說,則是設定CR3寄存器為新的pgd。有人會問,這裡切換了新的pgd,那麼代碼執行會不會不連續了? 沒關係,因為現在是核心空間,核心地址空間的頁面映射不會隨著pgd而改變。

1966     /* Here we just switch the register state and the stack. */1967     switch_to(prev, next, prev);1968 1969     barrier();1970     /*1971      * this_rq must be evaluated again because prev may have moved1972      * CPUs since it called schedule(), thus the 'rq' on its stack1973      * frame will be invalid.1974      */1975     finish_task_switch(this_rq(), prev);1976 } 

進程切換的硬體上下文是共用的CPU 寄存器,進程在切換時,硬體上下文儲存在task_struct->thread欄位中,注意thread是體繫結構特定的,所以不是每個體繫結構都需要儲存寄存器到這個結構中的。swtich之後的代碼,只有在當前進程下一次被選擇執行時才會執行。

barrier確保switch_to和後面的finish_task_switch不會亂序執行。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.