1. 程式人生 > >【轉載】Linux記憶體管理與相關概念

【轉載】Linux記憶體管理與相關概念

    在Linux中經常發現空閒記憶體很少,似乎所有的記憶體都被系統佔用了,表面感覺是記憶體不夠用了,其實不然。Linux記憶體管理的一個特點是無論實體記憶體有多大,Linux 都將其充分利用(The reason Linux uses so much memory for disk cache is because the RAM is wasted if it isn’t used)。

一、記憶體相關概念

1.實體記憶體與虛擬記憶體

    實體記憶體就是系統硬體提供的記憶體大小,是真正的記憶體(一般指RAM),相對於實體記憶體,在linux下還有一個虛擬記憶體的概念,虛擬記憶體就是為了滿足實體記憶體的不足而提出的策略,它是利用磁碟空間虛擬出的一塊邏輯記憶體,用作虛擬記憶體的磁碟空間被稱為交換空間(Swap Space)。     作為實體記憶體的擴充套件,linux會在實體記憶體不足(注意這一條件,這一條件的量化分析請參考https://www.douban.com/note/349467816/)時,使用交換分割槽的虛擬記憶體,更詳細的說,就是核心會將暫時不用的記憶體塊資訊寫到交換空間,這樣以來,實體記憶體得到了釋放,這塊記憶體就可以用於其它目的,當需要用到原始的內容時,這些資訊會被重新從交換空間讀入實體記憶體。     Linux的記憶體管理採取的是分頁存取機制(詳細可參考http://www.linuxeye.com/Linux/1931.html),為了保證實體記憶體能得到充分的利用,核心會在適當的時候將實體記憶體中不經常使用的資料塊自動交換到虛擬記憶體中,而將經常使用的資訊保留到實體記憶體。     要深入瞭解linux記憶體執行機制,需要知道下面提到的幾個方面:

    (1)Linux系統會根據系統配置不時地進行頁面交換操作,以保持一定量的空閒實體記憶體,有些配置下即使並沒有什麼事情需要記憶體,Linux也會交換出暫時不用的記憶體頁面。這可以避免等待交換所需的時間。相關的配置有/etc/sysctl.conf中的vm.swappiness配置(配製方法請參考http://www.vcaptain.com/?id=17),該引數的作用簡單描述就是“當 swappiness 內容的值為 0 時,表示最大限度地使用實體記憶體,實體記憶體使用完畢後,才會使用 swap 分割槽;當 swappiness 內容的值為 100 時,表示積極地使用 swap 分割槽,並且把記憶體中的資料及時地置換到 swap 分割槽。Linux 系統初始安裝完成時,其預設值為 60, 這表示空閒實體記憶體少於 60% 時開始啟用記憶體置換演算法,將記憶體中不常使用的資料置換到 swap 分割槽。”(具體如何起作用請參考https://www.douban.com/note/349467816/)

    (2)Linux 進行頁面交換是有條件的,不是所有頁面在不用時都交換到虛擬記憶體,linux核心根據”最近最經常使用“演算法,僅僅將一些不經常使用的頁面檔案交換到虛擬 記憶體,有時我們會看到這麼一個現象:linux實體記憶體還有很多,但是交換空間也使用了很多。其實,這並不奇怪,例如:一個佔用很大記憶體的程序執行時,需要耗費很多記憶體資源,此時就會有一些不常用頁面檔案被交換到虛擬記憶體中,但後來這個佔用很多記憶體資源的程序結束並釋放了很多記憶體時,剛才被交換出去的頁面 檔案並不會自動的交換進實體記憶體,除非有這個必要,那麼此刻系統實體記憶體就會空閒很多,同時交換空間也在被使用,就出現了剛才所說的現象了。關於這點,不用擔心什麼,只要知道是怎麼一回事就可以了。

    (3)交換空間的頁面在使用時會首先被交換到實體記憶體,如果此時沒有足夠的實體記憶體來容納這些頁 面,它們又會被馬上交換出去,如此以來,虛擬記憶體中可能沒有足夠空間來儲存這些交換頁面,最終會導致linux出現假宕機、服務異常等問題,linux雖然可以在一段時間內自行恢復,但是恢復後的系統已經基本不可用了。     分配太多的Swap空間會浪費磁碟空間,而Swap空間太少,則系統會發生錯誤。 如果系統的實體記憶體用光了,系統就會跑得很慢,但仍能執行;如果Swap空間用光了,那麼系統就會發生錯誤。例如,Web伺服器能根據不同的請求數量衍生出多個服務程序(或執行緒),如果Swap空間用完,則服務程序無法啟動,通常會出現“application is out of memory”的錯誤,嚴重時會造成服務程序的死鎖。因此Swap空間的分配是很重要的。

2.buffer 與 cache

    在Linux 作業系統中,當應用程式需要讀取檔案中的資料時,作業系統先分配一些記憶體,將資料從磁碟讀入到這些記憶體中,然後再將資料分發給應用程式;當需要往檔案中寫 資料時,作業系統先分配記憶體接收使用者資料,然後再將資料從記憶體寫到磁碟上。然而,如果有大量資料需要從磁碟讀取到記憶體或者由記憶體寫入磁碟時,系統的讀寫性 能就變得非常低下,因為無論是從磁碟讀資料,還是寫資料到磁碟,都是一個很消耗時間和資源的過程,在這種情況下,Linux引入了buffers和 cached機制。     buffers與cached都是記憶體操作,用來儲存系統曾經開啟過的檔案以及檔案屬性資訊,這樣當作業系統需要讀取某些檔案時,會首先在buffers 與cached記憶體區查詢,如果找到,直接讀出傳送給應用程式,如果沒有找到需要資料,才從磁碟讀取,這就是作業系統的快取機制,通過快取,大大提高了操 作系統的效能。但buffers與cached緩衝的內容卻是不同的。     buffers是用來緩衝塊裝置做的,它只記錄檔案系統的元資料(metadata)以及 tracking in-flight pages,而cached是用來給檔案做緩衝。更通俗一點說:buffers主要用來存放目錄裡面有什麼內容,檔案的屬性以及許可權等等。而cached直接用來記憶我們開啟過的檔案和程式。(Buffers are associated with a specific block device, and cover caching of filesystem metadata as well as tracking in-flight pages. The cache only contains parked file data. That is, the buffers remember what’s in directories, what file permissions are, and keep track of what memory is being written from or read to for a particular block device. The cache only contains the contents of the files themselves.)