進程的調度是進程部分的核心-很顯然,若是沒有調度,咱們也不須要進程了!咱們在上一篇文章的第二部分實現了一個最簡單的按照時間片的調度算法,每一個進程都平均執行100毫秒。java
while (true){ processing = nextProcessing(); processing.run(); wait(100); //每100毫秒分片 processing.interrupt(); }
那麼Linux中如何實現的呢?咱們先來看流程。調度相關的代碼都在sched.c
中。這個就是Linux代碼核心中的核心,它被運行在億萬臺機器上,每臺機器每一個時鐘週期就要執行一次,看到它是否是有點激動?終於知道「高性能的底層代碼」長什麼樣了!linux
這個文件的核心函數是asmlinkage void __sched schedule(void)
,這就是調度部分的具體代碼。當我讀完並註釋以後才發現已經有不少註釋版本了,好比這篇文章:http://blog.csdn.net/zhoudaxia/article/details/7375836,因此就不貼代碼了。我註釋後的代碼在sched.c(4079行開始)裏。不過不讀源碼,不用那些關鍵詞去搜索,估計也找不到一些好文章,這也是一個學習的過程吧。git
這個方法有兩個重要的點,一個是pick_next_task(rq);
,獲取下一個可執行進程,它涉及到調度算法;一個是context_switch(rq, prev, next);
,這就是所謂的「上下文切換」了。github
咱們前面的「100毫秒算法」算法固然是很是粗糙的。在瞭解貨真價實的Linux調度算法時,不妨看看,調度系統須要考慮什麼問題(非官方不權威總結):算法
咱們的「100毫秒算法」不知足1和3,對於2來講其實也不太好(可能有些進程都不會執行那麼久)。若是咱們把時間縮短,換成1毫秒怎麼樣呢?咱們知道,「進程切換」自己也有開銷,這樣子頻繁切換,豈不是得不償失了?函數
實際上,由於其核心地位,Linux的調度算法一旦提高一點點性能,對整個工業界的提高也是巨大的。對於算法高手來講,這裏成了大顯身手的好地方。因此Linux調度算法的變化那是至關的快,從O(n)調度器到O(1)調度器,再到2.6.23中的"CFS(completely fair schedule)",讓人看得都暈了!性能
瞭解了要解決的問題,或許會更容易理解一點。O(n)和O(1)算法都是基於時間片的,基本思路就是:給進程指定優先級,IO高、交互強的進程給予更高的優先級,CPU佔用高的則下降優先級,每次選優先級最高的執行;同時爲每一個進程分配時間片(每一個進程的時間片都是動態調整的),每一個進程每次執行的時間就是這個時間片的時間。O(n)和O(1)的區別在於從優先級隊列裏取進程的時候的時間複雜度而已。具體細節就很少說了。學習
而"CFS"則是使用了一個"vruntime"的概念來保存執行時間。同時它用一顆紅黑樹來對進程作排序,vruntime越小的進程會被越先執行,因此它的時間複雜度是O(logn)。它的代碼在kernel/sched_fair.c
中。.net
另外還有個「實時調度算法」的概念。這些就是「加塞的」的進程,它們優先於CFS的全部進程。對應的類型是SCHED_FIFO
和SCHED_RR
,在sched.h
中能夠看到。設計
調度部分就這麼多,還有些細節,例如CFG具體實現,書裏已經很詳細了,就不重複記錄,省得寫暈了!