![](http://static.javashuo.com/static/loading.gif)
![](http://static.javashuo.com/static/loading.gif)
linux內存管理卷帙浩繁,本文只能層層遞進地帶你領略冰山輪廓,經過本文你將瞭解到如下內容:linux
爲何須要管理內存web
linux段頁管理機制算法
內存碎片的產生機理緩存
爲何須要管理內存
老子的著名觀點是無爲而治,簡單說就是不過多幹預而充分依靠自覺就能夠有條不紊地運做,理想是美好的,現實是殘酷的。微信
在linux系統中若是以一種原始簡單的方式管理內存是存在一些問題的,咱們來看幾個場景。app
內存管理的問題
進程空間隔離問題 假如如今有ABC三個進程運行在linux的內存空間,設定os給進程A分配的地址空間是0-20M 進程B地址空間30-80M,進程C地址空間90-120M,如圖:編輯器
在某些時候程序空間的訪問可能出現問題,好比進程A訪問了屬於進程B的空間,進程B訪問了屬於進程C的空間,甚至修改了空間的值,這樣就會形成混亂和錯誤,因此實際中是不容許這種狀況發生的。ide
內存效率和內存不足問題性能
機器的內存是有限資源,而進程數量是沒法肯定的,若是在某些時候已經啓動的進程佔據了全部內存空間,此時就沒法啓動新進程了,由於沒有新內存可分配了,可是咱們觀察到已經啓動的進程有時候是在睡大覺,也就是給了內存也不用,這樣效率確實是有點低,因此咱們須要一個管理員把不用的內存倒騰出來,另外連續內存實在是很珍貴,不少時候咱們無法有效及時地分配連續內存,所以虛擬化和離散化可能會有效提升內存的使用率。flex
程序定位調試和編譯運行問題
因爲程序運行時的位置時不肯定的,咱們在定位問題、調試代碼、編譯執行時都會存在不少問題,咱們但願每一個進程有一致且完整的地址空間,一樣的起始位置放置了堆、棧以及代碼段等,從而簡化編譯和執行過程當中的 linker 連接器、loader 加載器的使用。
虛擬地址空間
爲了解決上述的一些問題,linux系統引入了虛擬空間的概念,虛擬化的出現和硬件有密不可分的聯繫,能夠說是軟硬件組合的結果,虛擬地址空間就是在程序和物理空間所增長的中間層,這也是內存管理的重點。
磁盤 disk 做爲一種大容量的存儲也做爲"內存"的一部分參與程序的運行,內存管理系統會將不經常使用非活躍內存進行頁面換出,能夠認爲內存是磁盤的緩存,內存中保留了活躍的數據,從而間接擴展了有限的物理內存空間,這部分空間稱爲虛擬內存是相對於物理內存而言的。
段頁管理機制
本文並不深刻地將分段管理內存和分頁管理內存,由於將這些細節的優秀文章不少,感興趣的使用搜索引擎一鍵即達。
段頁機制也不是一蹴而就的,經歷了單純物理分段、單純分頁、單純邏輯分段等階段,最終演進出來了分段和分頁結合的內存管理方式,段頁結合得到了分段和分頁的優點也避免了單一模式的弊端,是一種比較好的管理模式。
本文對於段頁管理機制只想通俗地說明一些概念,段頁管理機制是分段式管理和分頁式管理的組合,段式管理是邏輯上的管理方式,分頁管理是偏物理上的管理方式。
計算機裏面的一些技術和實現均可以在現實生活中找到縮影,所謂藝術和科技源自生活大概就是這個意思吧。
舉個栗子:
在進行居民戶籍管理時都會有區縣市的概念,可是實際上並無這種實體,都是邏輯上的,增長了這些行政單位以後可讓地址管理更加直接。
對於咱們居民來講惟一的實體就是本身的房子住所,這是物理上的單位,是真實存在的,這也是最基本的單位。
對比linux段頁時管理來講,段是邏輯上的單位至關於區縣市的概念,頁是物理上的單位至關於小區/房屋的概念,這樣就方便不少。
多級頁表也很好理解,總的物理內存假若有4GB,頁大小爲4KB,那麼就總共有2^20個頁,數量仍是很是大的,這樣編號來創建索引尋址比較不方便,因此引入多級頁表,來減小存儲便於管理。
段頁機制加持下的邏輯地址和物理地址的映射關係簡圖,也就是虛擬地址到物理地址的對應關係:
內存管理單元( MMU Memory Management Unit )是硬件層組件,主要提供將虛擬地址映射爲物理地址。
MMU 的工做流程:CPU 生成邏輯地址交給分段單元,分段單元進行處理將邏輯地址轉換爲線性地址,再線性地址交給分頁單元,分頁單元根據頁表映射轉換內存物理地址,其中可能出現缺頁中斷。
缺頁中斷( Page Fault )是隻當軟件試圖訪問一個虛擬地址時,通過段頁轉換爲物理地址以後,此時發現該頁並無在內存中,這時 cpu 就會報出中斷,再進行相關虛擬內存的調入工做或者分配工做,若是出現異常也可能直接中斷。
物理內存和內存碎片
前面說的段頁管理機制算是虛擬空間的部分,然而linux內存管理的另一個重要部分就是物理內存的管理了,也就是如何分配和回收物理內存,這就涉及到一些內存分配算法和分配器。
物理內存分配器
分配器和分配算法就像公司財務,內存就像公司資金,如何把資金合理使用是財務的本職工做,如何把物理內存合理使用是分配器的份內之事。
內存碎片分類和機理
若是咱們不知道內存碎片是什麼,試想一下咱們常說的碎片化的時間,也就是那些雖然空閒可是沒有被利用的時間,其實內存也是如此。
不管是時間仍是內存被碎片化以後都沒法被有效利用,所以合理管理減小碎片對咱們來講是相當重要的,這也是物理內存分配算法和分配器的研究重點。
按照碎片的位置和產生緣由,內存碎片分爲外部碎片和內部碎片,咱們看下這兩種碎片的直觀展現:
從圖中能夠知道,外部碎片是進程與進程間未分配的內存空間,外部碎片的出現和進程頻繁的分配和釋放內存有直接關係,這個很好理解,模擬一下分配不一樣空間的進程不一樣時間釋放就能夠看到外部碎片的產生了。
內部碎片主要由於分配器粒度問題以及一些地址限制致使實際分配的內存大於所需內存,這樣在進程內部就會出現內存空洞。
雖然虛擬地址讓進程使用的內存在物理內存上是離散的,可是不少時候進程須要必定量連續物理內存,若是大量碎片存在,就會形成沒法啓動進程的問題,如圖Process7須要一塊連續的物理內存卻沒法被分配:
在Linux系統下,監控內存經常使用的命令是free、top等,下面是一個free命令的執行結果:
要了解Linux的內存管理,首先要明白上例中各個名詞的意義:
total:物理內存的總大小。
used:已經使用的物理內存多小。
free:空閒的物理內存值。
shared:多個進程共享的內存值。
buffers / cached:用於磁盤緩存的大小(這部分是從物理內存中劃出來的)。
第二行Mem:表明物理內存使用狀況。
第三行(-/+ buffers/cached):表明磁盤緩存使用狀態。
第四行:Swap表示交換空間內存使用狀態(這部分其實是從磁盤上虛擬出來的邏輯內存)。
free命令輸出的內存狀態,能夠從兩個角度來看:內核角度、應用層角度。
1. 從內核角度來查看內存的狀態:
就是內核目前能夠直接分配到,不須要額外的操做,即free命令第二行 Mem 的輸出。從上例中可見,41940 + 16360492 = 16402432,也就是說Mem行的 free + used = total,注意,這裏的free並不包括buffers和cached。
2. 從應用層角度來查看內存的狀態:
也就是Linux上運行的程序可使用的內存大小,即free命令第三行 -/+ buffers/cache 的輸出。再來作一個計算41940+(465404+12714880)=13222224,即Mem行的free + buffers + cached = -/+ buffers/cache行的free,也就是說應用可用的物理內存值是Mem行的free、buffers和cached三者之和,可見-/+ buffers/cache行的free是包括buffers和cached的。
對於應用程序來講,buffers/cached佔有的內存是可用的,由於buffers/cached是爲了提升文件讀取的性能,當應用程序須要用到內存的時候,buffers/cached會很快地被回收,以供應用程序使用。
物理內存和虛擬內存 物理內存就是系統硬件提供的內存大小,是真正的內存。在linux下還有一個虛擬內存的概念,虛擬內存就是爲了知足物理內存的不足而提出的策略,它是利用磁盤空間虛擬出的一塊邏輯內存,用做虛擬內存的磁盤空間被稱爲 交換空間(Swap Space) 。
linux的內存管理採起的是分頁存取機制,爲了保證物理內存能獲得充分的利用,內核會在適當的時候將物理內存中不常用的數據塊自動交換到虛擬內存中,而將常用的信息保留到物理內存。而進行這種交換所遵循的依據是「LRU」算法(Least Recently Used,最近最少使用算法)。
最後介紹下Buffers和Cached有什麼用
在任何系統中,文件的讀寫都是一個耗時的操做,當應用程序須要讀寫文件中的數據時,操做系統先分配一些內存,將數據從磁盤讀入到這些內存中,而後應用程序讀寫這部份內存數據,以後系統再將數據從內存寫到磁盤上。若是是大量文件讀寫甚至重複讀寫,系統讀寫性能就變得很是低下,在這種狀況下,Linux引入了緩存機制。
buffers與cached都是從物理內存中分離出來的,主要用於實現磁盤緩存,用來保存系統曾經打開過的文件以及文件屬性信息,這樣當操做系統須要讀取某些文件時,會首先在buffers與cached內存區查找,若是找到,直接讀出傳送給應用程序,不然,才從磁盤讀取,經過這種緩存機制,大大下降了對磁盤的IO操做,提升了操做系統的數據訪問性能。而這種磁盤高速緩存則是基於兩個事實:第一,內存訪問速度遠遠高於磁盤訪問速度;第二,數據一旦被訪問,就頗有可能短時間內再次被訪問。
另外,buffers與cached緩存的內容也是不一樣的。buffers是用來緩衝塊設備作的,它只記錄文件系統的元數據(metadata)以及 tracking in-flight pages,而cached是用來給文件作緩衝。更通俗一點說:buffers主要用來存放目錄裏面有什麼內容,文件的屬性以及權限等等。而cached直接用來記憶咱們打開過的文件和程序。
爲了驗證咱們的結論是否正確,能夠經過vi打開一個很是大的文件,看看cached的變化,而後再次vi這個文件,感受一下是否是第二次打開的速度明顯快於第一次?
接着執行下面的命令:
find /* -name *.conf
看看buffers的值是否變化,而後重複執行find命令,看看兩次顯示速度有何不一樣。
Linux內存管理的哲學
Free memory is wasted memory.
Linux的哲學是儘量多的使用內存,減小磁盤IO,由於內存的速度比磁盤快得多。 Linux老是在力求緩存更多的數據和信息,內存不夠時,將一些不常用的數據轉移到交換分區(Swap Space)中以釋放更多可用物理內存,固然,若是交換分區的數據再次被讀寫時,又會被轉移到物理內存中,這種設計思路提升了系統的總體性能。而Windows的處理方式是,內存和虛擬內存一塊兒使用,不是之內存操做爲主,結果就是IO的負擔比較大,可能拖慢處理速度。
Linux和Windows在內存管理機制上的區別
在Linux系統使用過程當中,你會發現,不管你的電腦內存配置多麼優越,仍然不時的發生可用內存吃緊的現象,感受內存不夠用了,其實否則。這是Linux內存管理的優秀特性,不管物理內存有多大,Linux都將其充分利用,將一些程序調用過的硬盤數據緩存到內存,利用內存讀寫的高速性提升系統的數據訪問性能。而Window只在須要內存時,才爲應用分配內存,不能充分利用大容量的內存空間。 換句話說,每增長一些內存,Linux都能將其利用起來,充分發揮硬件投資帶來的好處,而Windows只將其做爲擺設。
因此說,通常咱們不須要太關注Linux的內存佔用狀況,而若是Swap佔用率一直居高不下的話,就頗有可能真的是須要擴展內存了。
夯實基礎,關注前沿,娛樂生活
掌握更多前沿技術,獲取更多笑點
請關注--------喘口仙氣
本文分享自微信公衆號 - 喘口仙氣(gh_db8538619cdd)。
若有侵權,請聯繫 support@oschina.cn 刪除。
本文參與「OSC源創計劃」,歡迎正在閱讀的你也加入,一塊兒分享。