應用層一般專一於API的使用,認爲將其當作是一個黑盒便可,但瞭解操做系統的一些機制將有助於咱們更好地使用它,也有助於避免犯錯誤。linux
1969年,unix從貝爾實驗室誕生,由一個失敗的操做系統multics發展而來,它發佈時帶上了源碼,以致於不少組織都對其進一步改進。它由C語言編寫,且只有幾百個系統調用,秉承一切皆文件的設計思想。算法
由芬蘭大學生linus在1991年開發,基於Intel80386微處理器,開發完後就在因特網發佈了源碼。它借鑑了unix的不少設計思想,但它的實現徹底不一樣,算是一個不一樣的操做系統。開源協議很是自由,能夠自由修改,但須要將改過的源碼繼續發佈出來。shell
操做系統負責最基本的功能和系統管理,包括內核、設備驅動、啓動引導、shell、界面、文件管理、其它系統工具。應用程序一般經過庫函數,庫函數經過系統調用讓內核去完成各類任務。數據結構
進程是處於執行期的程序,它包含各類資源,好比文件、信號、內核數據、處理器狀態、內存空間、執行線程、全局數據段等。進程提供了虛擬處理器和虛擬內存,看起來進程就像本身獨享相應資源。併發
內核將全部進程保存在任務隊列中,它是一個雙向循環鏈表,該鏈表中每一個節點的類型都是task_struct進程描述符結構,處於<linux/sched.h>中。機器學習
全部進程都是PID爲1的init進程的後代,內核啓動的最後階段啓動init進程,它負責讀取系統的初始化腳本並執行其它相關程序。每一個進程都有一個父進程,每一個進程也均可以有零個或多個子進程。fork()用於建立子進程,它經過拷貝當前進程來建立一個子進程,父子進程區別在於PID、PPID、某些資源、統計量不一樣。fork()使用了寫時拷貝機制,父進程和子進程共享同一個拷貝,只有須要寫入時數據纔會被複制。fork()的實際開銷就是複製父進程的頁表以及給子進程建立惟一進程描述符。exec()負責讀取可執行文件並將其載入空間開始運行。進程調用exit()系統調用時進程被終結。分佈式
線程是進程的活動對象,每一個線程都擁有獨立的程序計數器、進程棧和一組寄存器。線程能在同一程序裏面共享內存地址空間,共享文件和其它資源。從內核角度來講linux並無線程這個概念,它將線程當成是進程來看待。內核線程沒有獨立的地址空間,只運行在內核空間,從不切換到用戶空間。模塊化
進程調度器的目的就是最大限度地利用CPU時間,只要有可執行的任務就要儘可能去執行它們,但咱們知道系統中幾乎老是任務數大於處理器個數,因此確定某個時刻有任務得不到執行。多任務系統能併發地執行多個進程,一個CPU時是一對多,多個CPU時是多對多,全部任務看起來就像是同時在運行同樣。函數
多任務系統分爲搶佔式和非搶佔式,linux是搶佔式調度,調度程序來決定進程的掛起和執行,每一個進程能執行的時間爲時間片,現代系統通常都有必定的策略來動態分配時間片。非搶佔式則是由進程本身主動中止,不然將一直運行下去,調度程序沒法決定進程的運行中止,若是某個進程一直運行則會使系統奔潰。工具
進程可分爲I/O密集型和處理器密集型。前者大部分時間進行各類I/O請求,一般這些進程只運行很短一段時間,而後就在I/O上阻塞了。然後者則是大部分時間都用於代碼執行上,不停地運行並且沒有什麼I/O請求。固然有些進程既是I/O密集型也是處理器密集型。對於前者咱們但願時間片少一點,對於後者咱們但願時間片多一點,調度策略就是要在兩個矛盾中找到平衡,使得進程可以響應迅速又能最大系統利用率。
基於優先級的調度是最基本的一種調度算法,它把進程進行了分級,優先級高的先運行,優先級低的後運行,相同優先級的進程則輪流運行。某些系統中優先級高的進程將更頻繁運行,且時間片也更長。調度程序選擇時間片未用盡且優先級最高的進程來執行。linux有兩種優先級範圍,第一種是nice值,從-20到+19,默認爲0,值越大優先級越低。第二種是實時優先級,默認範圍是0到99,值越高表示優先級越高。任何實時進程的優先級都高於普通進程,也就是說nice優先級和實時優先級是兩個不一樣維度。
時間片是進程在被搶佔前所能持續運行的時間,默認的時間片大小不容易肯定,時間片太長會使交互響應變差,時間片過短會增長進程切換帶來的損耗。也就是前面說到的矛盾,I/O密集型但願時間片短點,而處理器密集型則但願時間片長點。
linux採用了徹底公平調度(CFS)算法,它是一個針對普通進程的調度器,linux中稱爲SCHED_NORMAL,而POSIX則稱爲SCHED_OTHRER,實現類在kernel/sched_fair.c中。CFS容許每一個進程運行一段時間、循環輪轉、選擇運行最少的進程做爲待運行進程,CFS計算全部可運行進程總數做爲基礎,再計算一個進程應該運行多久,而不是靠優先級來計算時間片。CFS有一個最小時間片(最小粒度),默認是1ms。也就是說就算有無窮大個進程,每一個進程最少也能有1ms時間片。CFS確保給每一個進程公平的處理器使用比。
linux提供了兩種實時調度策略:SCHED_FIFO和SCHED_RR。前者是一種簡單的先入先出調度算法,它不使用時間片。處於SCHED_FIFO級別的進程會比任何SCHED_NORMAL級別的進程先獲得調度。一旦某個SCHED_FIFO級別的進程處於可執行狀態,它將會一直執行,直到它本身阻塞或顯示釋放CPU。只有更高優先級的SCHED_FIFO或SCHED_RR進程才能搶佔它。兩個相同優先級的SCHED_FIFO級別的進程會輪流執行,其它普通進程只能等它變爲不可運行狀態後纔有機會執行。
SCHED_RR大體與SCHED_FIFO相同,但它是耗盡事先分配的時間後就再也不繼續執行,即SCHED_RR是帶了時間片的SCHED_FIFO。時間片只是相對於同一優先級的進程,低優先級的進程沒法搶佔SCHED_RR任務,即便它的時間片耗盡也不行。
linux 經過sched_yield()系統調用來放棄當前進程的處理器時間,讓給其餘待執行進行,對於實時進程,它會將進程從活動隊列中移到其優先級隊列的後面。早期linux的yield語義不同,只會將進程放到優先級隊列的末尾,放棄的時間不會太長。
專一於人工智能、讀書與感想、聊聊數學、計算機科學、分佈式、機器學習、深度學習、天然語言處理、算法與數據結構、Java深度、Tomcat內核等。