"點我查看秘籍連載" OOM和swap分區 進程的虛擬記憶體空間是映射到整個物理記憶體空間的,所以在進程自身看來它擁有了整個物理記憶體,它也能使用整個物理記憶體,只需在使用的時候請求操作系統幫忙分配更多空間即可。 但是,操作系統上並非只運行了一個進程,如果一個進程無休止的申請物理記憶體空間,最終會導致物理記憶體 ...
OOM和swap分區
進程的虛擬記憶體空間是映射到整個物理記憶體空間的,所以在進程自身看來它擁有了整個物理記憶體,它也能使用整個物理記憶體,只需在使用的時候請求操作系統幫忙分配更多空間即可。
但是,操作系統上並非只運行了一個進程,如果一個進程無休止的申請物理記憶體空間,最終會導致物理記憶體耗盡或即將耗盡,使得操作系統無法創建新進程,因為創建新進程需要為它分配虛擬記憶體。
所以,操作系統必須得監視物理記憶體的使用情況,在出現物理記憶體耗盡或即將耗盡的時候,如果進程繼續請求分配記憶體,將報錯out-of-memory(OOM)表示記憶體不足,並且在出現OOM的時候,操作系統將觸發OOM Killer程式從進程列表中篩選出一個記憶體密集型進程殺掉,從而釋放大片記憶體。但顯然,這是不怎麼友好的方式,不少伺服器都專門或主要運行一個服務,如果這個服務進程正好申請了大量記憶體,它很可能會被OOM Killer殺掉,從而導致服務停止。
其實,早期記憶體一般都比較小,很容易就出現記憶體不足的問題,所以很早就提出了一個交換分區(swap partition)的概念。
swap分區是將磁碟當作記憶體使用,使得虛擬地址空間的範圍大小可以超出物理記憶體的實際大小,在物理記憶體空間不足時,可以將物理記憶體中的一些不重要數據拷貝到磁碟的swap分區中,從而讓出記憶體空間,並且在需要那些已被拷出數據時再從swap分區中拷回到記憶體,從而不再那麼容易發生OOM錯誤。
但是swap分區畢竟是在磁碟上,並且要在記憶體和磁碟之間傳遞數據,所以要訪問swap分區上的數據時速度會非常慢。在目前大記憶體都已足夠廉價的情況下,已經沒有多少必要使用swap分區。
雖然,現在swap分區對進程來說很少派上用場,但涉及到的一些技術和概念有必要簡單介紹下。
使用swap分區第二個要解決的問題是,如何讓虛擬地址空間的頁映射到磁碟swap分區的頁上。也就是,如何將虛擬頁翻譯成swap頁,並且在訪問時怎麼知道這不是記憶體的物理頁。
因為在物理記憶體的基礎上引入了swap分區,所以每個虛擬頁中都有一個存在位來表示該頁是否存在於記憶體中,如果該位的值為1,表示駐留在記憶體中,如果為0則表示在swap分區而非記憶體。其中,所有駐留在記憶體中的頁也稱為駐留集(Resident Set)。
當訪問一個虛擬頁的時候,如果發現不在記憶體中,這時候會產生缺頁異常(page fault),也稱為頁未命中(page miss),於是陷入操作系統,啟動頁錯誤處理程式,從swap分區中找到對應的頁(顯然,這裡需要將虛擬記憶體頁翻譯成swap分區頁的地址)並拷貝到記憶體中。從swap分區拷入頁的過程稱為換入頁(page in)。
這裡產生了一個新問題,既然已經使用了swap分區,說明此時物理記憶體已經處於緊張狀態,從swap中page in的頁如何放進記憶體中?其實,這裡也需要先進行page out,將該進程的一頁或多頁page out以便騰出記憶體。那麼哪些運氣不好的頁會被page out呢?這裡又出現了策略演算法,稱為頁替換策略演算法,用來決定哪些頁應該被page out,比如使用FIFO演算法換出那些先進入的頁,使用隨機演算法隨機選擇換出的頁,使用LRU演算法選擇最近最不常用的頁等等。
其實,除了page out換出頁騰出少量記憶體空間外,操作系統還設置了兩個關於空閑頁數量(顯然,這是物理頁)的水位線:高水位線(High Watermark,HW)和低水位線(Low Watermark,LW)。當操作系統發現空閑頁的數量少於低水位線的值時,就會自動啟動一個稱為swap daemon(也稱為page daemon)的後臺線程kswapd,該線程會掃描所有進程並從中選出一些候選進程,然後將這些進程的所有頁都拷貝到swap分區,直到空閑物理記憶體頁的數量達到高水位線的值。
提示:高水位線和低水位線
在電腦領域中,常會使用高水位線和低水位線來監視進程的一些可用性資源。當這類可用性資源的數量高於或臨近高水位線的值時,表明資源充足。當可用性資源的數量已經低於低水位線,說明資源緊張,應當採取一些措施恢復一些資源。
其中,換出進程所有頁到swap分區的過程稱為swap out,而從swap分區拷入進程所有頁的過程(比如再次調度到該進程)稱為swap in。將這兩個概念與page out和page in區分以下:
- page in和page out是拷入或拷出進程的一頁或某些頁
- swap in和swap out是拷入或拷出進程的所有頁
關於swap分區,能不用的話最好還是不用,因為當真正用到swap分區的時候,記憶體已經進入了緊張狀態,之後的絕大多數進程基本上都會涉及到swap分區,不斷地出現page fault而進行換頁,這會導致進程抖動(thrashing),使得整體效率低下,而且這個狀態是持續的,直到釋放足夠的記憶體空間。這時候還不如採取其它辦法釋放記憶體空間,例如殺掉某些無關進程、重啟記憶體密集型服務、重啟機器等。