1. 程式人生 > >《Linux核心設計與實現》 讀書筆記

《Linux核心設計與實現》 讀書筆記

linux核心簡介

Linux系統的基礎是核心,C庫(庫函式裡會有些系統呼叫),工具集和系統的基本工具。

通常一個核心由負責響應中斷的中斷服務程式,負責管理多個程序從而分享處理器時間的排程程式,負責管理程序地址空間的記憶體管理程式,和網路、程序間通訊等系統服務程式共同組成。

當硬體裝置想要跟系統通訊的時候,首先要發出一個非同步的中斷訊號去打斷處理器的執行,繼而打斷核心的執行。

為了保證中斷服務程式能夠在第一時間響應和處理中斷請求,然後快速退出,中斷服務程式不在程序上下文中執行。

處理器在任何指定時間的活動必然為下列三者之一: 在這裡插入圖片描述

Unix核心幾乎毫無例外都是一個不可分割的靜態可執行庫,它們必須以巨大,單獨的可執行塊的形式在一個單獨的地址空間中執行。Unix核心通常需要硬體系統提供頁機制(MMU)以管理記憶體。

單核心 整個核心都在一個大核心地址空間上執行。

優點: 1.簡單。 2.高效:所有核心都在一個大的地址空間上,所以核心各個功能之間的呼叫和呼叫函式類似,幾乎沒有效能開銷。

缺點: 一個功能的崩潰會導致整個核心無法使用。

微核心 核心按功能被劃分成各個獨立的過程。每個過程獨立的執行在自己的地址空間上。

優點: 安全:核心的各種服務獨立執行,一種服務掛了不會影響其他服務。 可換出:允許一個伺服器為了另一個伺服器而換出。

缺點: 核心各個服務之間的呼叫涉及程序間的通訊,比較複雜且效率低。

Linux核心 Linux是一個單核心,不過,Linux汲取了微核心的精華:模組化設計、搶佔式核心、支援核心執行緒以及動態裝載核心模組的能力。(體現了Linux實用至上的原則)

Linux與傳統Unix系統之間的顯著差異:

1.支援動態載入核心模組; 2.支援對稱多處理(SMP)機制; 3.核心可以搶佔(preemptive),允許核心執行的任務有優先執行的能力; 4.核心不區分執行緒和其他的一般程序。對於核心來說,所有的程序都一樣——只不過是其中的一些共享資源而已。

在這裡插入圖片描述

程序管理

每個執行緒都擁有一個獨立的程式計數器,程序棧和一組程序暫存器。

程序提供兩種虛擬機制:虛擬處理器和虛擬記憶體。(線上程之間可以共享虛擬記憶體,但每個都擁有各自的虛擬處理器)

呼叫fork之後呼叫exec就可以建立新的地址空間,並把新的程式載入其中。

程序退出執行後被設定為僵死狀態,直到他的父程序呼叫wait函式。

核心把程序的列表存放在叫做任務佇列的雙向迴圈連結串列中,每一項都是稱為程序描述符的結構。

Linux通過slab分配器分配task_struct結構,這樣能達到物件複用和快取著色(參見12章)的目的(通過預先分配和複用,可避免動態分配和釋放所帶來的損耗)。

通過預先分配和重複使用task_struct,可以避免動態分配和釋放帶來的資源消耗。

核心通過一個唯一的程序標識值或PID來標識每個程序,PID是一個數,表示為pid_t隱含型別(實際上就是一個int型別)。

核心把每個程序的PID存放在它們各自的程序描述符中。

在這裡插入圖片描述

在這裡插入圖片描述

在中斷上下文中,系統不代表程序進行,而是執行一箇中斷處理程式,不會有程序去幹擾這些中斷處理程式,所以此時不存在程序上下文。

fork()使用的是寫時複製,fork的實際開銷就是複製父程序的頁表以及給子程序建立唯一的程序描述符

在Linux中,對核心來說,並沒有執行緒這個概念,它把所有的執行緒當做程序來實現,執行緒僅僅被視為一個與其他程序共享某些資源的程序。

核心經常需要在後臺執行一些操作。核心執行緒與普通程序的區別在於核心執行緒沒有獨立的地址空間(實際上指向地址空間的mm指標被設定為NULL)。它們只執行在核心空間,從來不切換到使用者空間。核心程序和普通程序一樣,可以被排程和搶佔。

程序終結之後,該程序關聯的資源被釋放掉了,但是它本身佔用的記憶體還沒有釋放,比如建立時分配的核心棧,thread_info結構和task_struct結構等。此時程序存在的唯一目的是向它的父程序提供資訊。父程序檢索到資訊後,或者通知核心那是無關的資訊後,該程序所持有的剩餘記憶體被釋放,歸還給系統使用。

父程序通過呼叫wait()一族的函式來檢測子程序是否存在。它的標準動作是掛起呼叫它的程序,直到其中一個子程序退出,此時函式會返回子程序的PID。此外,呼叫該函式時提供的指標會包含子函式退出時的退出程式碼。至此,程序描述符和所有程序獨享的資源就全部釋放掉了。

孤兒程序: 在這裡插入圖片描述

程序排程

程序排程程式是確保程序能有效工作的一個核心子系統。

多工系統可以劃分為兩類:非搶佔式多工和搶佔式多工。

Linux更傾向於優先排程IO消耗型程序,排程程式也並未忽略處理器消耗型的程序。

Linux採用了兩種不同的優先順序範圍(nice優先順序和實時優先順序)

Linux的CFS排程器(完全公平排程)則並沒有直接分配時間片到程序,而是將處理器的使用比劃分給程序,這樣程序獲得的處理器時間與系統負載密切相關。這個比例還受nice值影響,nice作為權重將調整程序使用處理器的時間比。

Linux的CFS排程器,搶佔時機取決於新的可執行程式消耗了多少處理器使用比,如果消耗的使用比比當前程序小,則新程序立刻投入執行,搶佔當前程序,否則推遲執行。(比如當前有個文字編輯器和個視訊解碼程式在執行,他們的優先順序相等,則分別有50%的處理器時間,實際上文字編輯器用不到50%,但是當文字編輯器有有新的輸入時檢測到他執行的時間少於50%,就會立即完成搶佔)

Linux的排程演算法(看課本4.4節)

CFS使用排程器實體結構(struct_sched_entity)來追蹤程序執行記賬。這個結構是程序描述符的一個成員變數。

搶佔和上下文切換:把虛擬記憶體從上一個程序對映切換到新程序。保留上一個程序的暫存器資訊等。

核心同步介紹和方法

所謂臨界區就是訪問和操作共享資料的程式碼段。程式設計者必須保證這些程式碼原子執行。避免併發和防止競爭條件稱為同步。

簡單的同步可以通過原子操作解決,複雜的需要加鎖。

在這裡插入圖片描述

自旋鎖:浪費處理器時間,所以不應該被長時間持有。用於在短時間內進行輕量級加鎖。

在這裡插入圖片描述

讀寫自旋鎖: 訊號量(計數訊號量和二值訊號量):一種睡眠鎖 讀寫訊號量: 互斥體(mutex):比訊號量相比,是更簡單的睡眠鎖(比訊號量簡潔,高效)

虛擬檔案系統

在這裡插入圖片描述