今天週六,又是清明節,我起床很晚,原因不是我懶,是因為我在被窩裡看書了,看的是《linux開發工具箱》,書是老外寫的,被翻譯成了中文,可以說翻譯的很差勁,很多地方感覺不通順,於是我吭吭哧哧半天過不去一句話,好在我的linux基礎比較好,讀此書不是為了獲取什麼知識,而是為了得到一種截然不同的表達或者理解方式罷了,書的整體結構還是比較明朗的,今天主要讀了第五章的第6節,講的是「使用者空間的記憶體管理」,本文就把這一章的收穫理一下。
首先說的就是虛擬記憶體,說到虛擬記憶體,我在前面的文章也說了,其實就是為了平衡確定和不確定之間的差異,確定的物理記憶體,不確定的是程序行為以及程序的數量,如果說每個程序占用大小為n的記憶體,那麼物理記憶體為m最多可以同時執行m/n個程序,其它的程序就必須等待這一輪的程序有乙個換出或者執行完畢或者阻塞之後才可以換進乙個,這樣的後果是,同時執行的程序頁面不會被換出,可以永駐記憶體,可是一旦由於阻塞或者時間片到期而換出記憶體就需要等待很長時間,程序一下子必須將其位址空間全部換出,然後輪到它執行時又要全部換入,這是一種很不好的情況,原因就在於,我們沒有必要讓乙個程序執行時其位址空間全部在記憶體,因為畢竟cpu一次只能訪問乙個位址,同時又不能忍受乙個程序為等待執行而等待太久,程序越多,程序的平均等待時間越久,於是這種粗粒度的換入換出方式必須改善。程序大小以及程序數量的不確定是個不可改變的事實,但是可是改變的是程序使用記憶體的方式,如果說不再是乙個程序乙個程序的換入換出,而是乙個頁面乙個頁面的換入換出,那麼就需要一套硬體機制和軟體策略來對映頁面和它的屬主程序,而且還要處理好共享關係。於是現在的頁式mmu體系就出現了,粒度很細,基於頁面,當然可以再細,但是那可能就會導致另外的問題。這裡就不再說cpu cacheline和tlb了。如此一來,新的虛擬記憶體體系建立了,所有的程序都有自己獨享的4g記憶體(32位位址匯流排),程序的大環境都相同了,不像以前那樣,每個程序的位址空間不同,現在mmu可以用統一的方式管理每個程序的4g空間了,管理更加高效。請求換頁的乙個缺點就是不再是基於程序的全域性換入換出了,這就造成了頁面置換的抖動,消除抖動的方式之一就是工作集,其實就是確保每個程序總會有一些頁面不被換出,而這些頁面就是最近經常被訪問的頁面。
這裡我想到的是linux作業系統核心的程序排程的粒度,原來的o(1)式的排程演算法,現在時cfs的演算法,前者更類似於原始的程序交換的記憶體管理,而後者的粒度更細,更像是頁式管理,在o(1)演算法中,雖然執行中的程序排程很有效,但是一旦到了過期佇列就要長等,為了避免這種長等,就必然引入了一系列的**演算法和硬限制條件,比如不能長等超過乙個時間等等,這樣的後果就是演算法及其複雜,最終還是會有一些抖動現象,而cfs就不錯,拋棄了很多複雜的演算法,細粒度可以做到完全公平。細粒度做到平均就是比粗粒度更加容易,做個試驗,手裡拿n個大小不同的球,放入乙個容器使勁搖,最後看看是否比較均勻,然後把這些球磨成粉,再搖,再看看,不要說這樣不可行,想想看,看它們的都是我們人。
接下來我比較感興趣的就是記憶體耗盡,書中用了很大的篇幅舉個好幾個例子來說明這一點。其實記憶體耗盡是乙個很明顯的現象,物理記憶體就那麼大,如果不注意,總會耗盡的。記憶體耗盡有兩種耗盡,一種是虛擬記憶體耗盡,另一種是物理記憶體耗盡,虛擬記憶體耗盡比較好理解,因為系統給程序的程式設計空間就是3g(linux大部分核心上)在程式設計的時候就不能耗盡這個大小的空間,當然沒有哪個程式設計師會知道自己用了多大的記憶體,那麼等到執行時會被檢測出來,其實虛擬空間耗盡就是在分配記憶體時發生的,而不是在訪問的時候,因為都是先分配虛擬記憶體,然後在訪問的時候再分配物理記憶體。
虛擬記憶體在linux中很多情況下一共有3g,應用程式可以隨意使用,可是glibc不太信任大多數的程式設計師,因此它實現了自己的管理方式,主要的動態記憶體管理方式就是堆記憶體和更大的用mmap分配的記憶體,glibc通過檢視malloc的引數,如果超過乙個限定值,那麼就不再從堆中分配,而是直接用mmap來分配,其實堆這種方式是從老的系統中繼承下來的,在mm_struct中就是brk欄位,brk系統呼叫可以擴充套件堆的空間,malloc分配小記憶體的時候,將直接使用glibc的堆管理器來在堆中分配,一旦池中沒有空閒塊,那麼就用brk從作業系統中分配,其實brk也是用mmap來分配的,只是它的起始位址引數是mm的brk欄位,而直接用mmap呼叫對映的記憶體的起始位址引數卻是可以在珍整個虛擬位址空間查詢的,而不管這塊虛擬位址在何方,這兒意義上,malloc可以從堆的池中分配,也可以用mmap直接分配,並且,brk只是乙個mmap實現的乙個包裝,只不過這個brk的實現在插入vma的時候必須用固定的位址罷了。
關於鎖定記憶體,linux提供了mlock和mlockall函式,後者可以將該程序的現有記憶體或者將來的記憶體鎖定在記憶體中,怎麼鎖定未來的記憶體呢?就是通過在該程序的mm_struct中設定乙個預設標誌,任何的mmap操作的標誌都需要或上這個預設標誌,在呼叫mlockall來鎖定未來記憶體的時候,只需要將這個預設標誌或上乙個lock標誌就可以了,很簡單吧。簡單是簡單,關鍵是很藝術。這個章節接下來的內容是程序的資源限制,其實就是set/getrlimit系統呼叫,這個系統呼叫就不多說了,這是linux的基本的程序管理限制機制,不過要說的是,在2.6.25後,實現了cgroup這種更加好的容器化的資源控制機制,更好的實現虛擬化而且可以讓不同的控制實體之間的聯絡更加緊密。
讀《linux開發工具箱》的一點感想
今天週六,又是清明節,我起床很晚,原因不是我懶,是因為我在被窩裡看書了,看的是 linux開發工具箱 書是老外寫的,被翻譯成了中文,可以說翻譯的很差勁,很多地方感覺不通順,於是我吭吭哧哧半天過不去一句話,好在我的linux基礎比較好,讀此書不是為了獲取什麼知識,而是為了得到一種截然不同的表達或者理解...
讀《linux開發工具箱》的一點感想
今天週六,又是清明節,我起床很晚,原因不是我懶,是因為我在被窩裡看書了,看的是 linux開發工具箱 書是老外寫的,被翻譯成了中文,可以說翻譯的很差勁,很多地方感覺不通順,於是我吭吭哧哧半天過不去一句話,好在我的linux基礎比較好,讀此書不是為了獲取什麼知識,而是為了得到一種截然不同的表達或者理解...
開源的DevOps開發工具箱
devops是一組過程 方法與系統的統稱,用於促進開發 應用程式 軟體工程 技術運營和質量保障 qa 部門之間的溝通 協作與整合。在devops的整個流程中,使用一些開源工具可以促進開發與運維之間的溝通,有利於專案的管理,甚至可以達到事半功倍的效果。本文作者richard kraaijenhagen...