亚洲国产婷婷六月丁香_婷婷精品免费久久久久电影院_99riav国产精品_91香蕉成人免费网站_91在线在线啪永久地址

快訊 >

系統(tǒng)內(nèi)存滿了,會(huì)發(fā)生什么

時(shí)間:2023-08-26 17:31:20       來(lái)源:清一色財(cái)經(jīng)

只有在訪問(wèn)已分配的虛擬地址空間的時(shí)候,操作系統(tǒng)通過(guò)查找頁(yè)表,發(fā)現(xiàn)虛擬內(nèi)存對(duì)應(yīng)的頁(yè)沒(méi)有在物理內(nèi)存中,就會(huì)觸發(fā)缺頁(yè)中斷,然后操作系統(tǒng)會(huì)建立虛擬內(nèi)存和物理內(nèi)存之間的映射關(guān)系。

前言

前面我們我們已經(jīng)了解了linux是如何進(jìn)行內(nèi)存分配的、虛擬內(nèi)存和物理內(nèi)存的關(guān)系、虛擬內(nèi)存如何管理,今天我們來(lái)學(xué)習(xí)一下系統(tǒng)內(nèi)存滿了,會(huì)發(fā)生什么?以及會(huì)帶來(lái)什么問(wèn)題?大致分成這四個(gè)內(nèi)容來(lái)進(jìn)行學(xué)習(xí)。

內(nèi)存分配的過(guò)程哪些內(nèi)存可以被回收內(nèi)存回收帶來(lái)的問(wèn)題如何保障一個(gè)進(jìn)程不被kill


(資料圖片僅供參考)

內(nèi)存分配的過(guò)程

前面我們已經(jīng)學(xué)習(xí)過(guò)應(yīng)用程序通過(guò) malloc 函數(shù)申請(qǐng)內(nèi)存的,需要注意的是,malloc() 分配的是虛擬內(nèi)存。

如果分配后的虛擬內(nèi)存沒(méi)有被訪問(wèn)的話,虛擬內(nèi)存是不會(huì)映射到物理內(nèi)存的,這樣就不會(huì)占用物理內(nèi)存了。

只有在訪問(wèn)已分配的虛擬地址空間的時(shí)候,操作系統(tǒng)通過(guò)查找頁(yè)表,發(fā)現(xiàn)虛擬內(nèi)存對(duì)應(yīng)的頁(yè)沒(méi)有在物理內(nèi)存中,就會(huì)觸發(fā)缺頁(yè)中斷,然后操作系統(tǒng)會(huì)建立虛擬內(nèi)存和物理內(nèi)存之間的映射關(guān)系。

缺頁(yè)中斷就是要訪問(wèn)的頁(yè)不在主存,需要操作系統(tǒng)將其調(diào)入主存后再進(jìn)行訪問(wèn)。在這個(gè)時(shí)候,被內(nèi)存映射的文件實(shí)際上成了一個(gè)分頁(yè)交換文件。

如果沒(méi)有空閑的物理內(nèi)存,那么內(nèi)核就會(huì)開(kāi)始進(jìn)行回收內(nèi)存的工作,回收的方式主要是兩種:直接內(nèi)存回收和后臺(tái)內(nèi)存回收。

后臺(tái)內(nèi)存回收(kswapd):在物理內(nèi)存緊張的時(shí)候,會(huì)喚醒 kswapd 內(nèi)核線程來(lái)回收內(nèi)存,這個(gè)回收內(nèi)存的過(guò)程異步的,不會(huì)阻塞進(jìn)程的執(zhí)行。直接內(nèi)存回收(direct reclaim):如果后臺(tái)異步回收跟不上進(jìn)程內(nèi)存申請(qǐng)的速度,就會(huì)開(kāi)始直接回收,這個(gè)回收內(nèi)存的過(guò)程是同步的,會(huì)阻塞進(jìn)程的執(zhí)行。

如果直接內(nèi)存回收后,空閑的物理內(nèi)存仍然無(wú)法滿足此次物理內(nèi)存的申請(qǐng),那么內(nèi)核就會(huì)放最后的大招了 ——觸發(fā) OOM 機(jī)制。

OOM Killer 機(jī)制會(huì)根據(jù)算法選擇一個(gè)占用物理內(nèi)存較高的進(jìn)程,然后將其殺死,以便釋放內(nèi)存資源,如果物理內(nèi)存依然不足,OOM Killer 會(huì)繼續(xù)殺死占用物理內(nèi)存較高的進(jìn)程,直到釋放足夠的內(nèi)存位置。

物理內(nèi)存申請(qǐng)過(guò)程如下圖:

哪些內(nèi)存可以被回收

系統(tǒng)內(nèi)存緊張的時(shí)候,就會(huì)進(jìn)行回收內(nèi)存的工作,那具體哪些內(nèi)存是可以被回收的呢?

主要有兩類內(nèi)存可以被回收,而且它們的回收方式也不同。

文件頁(yè)(File-backed Page):內(nèi)核緩存的磁盤(pán)數(shù)據(jù)(Buffer)和內(nèi)核緩存的文件數(shù)據(jù)(Cache)都叫作文件頁(yè)。大部分文件頁(yè),都可以直接釋放內(nèi)存,以后有需要時(shí),再?gòu)拇疟P(pán)重新讀取就可以了。而那些被應(yīng)用程序修改過(guò),并且暫時(shí)還沒(méi)寫(xiě)入磁盤(pán)的數(shù)據(jù)(也就是臟頁(yè)),就得先寫(xiě)入磁盤(pán),然后才能進(jìn)行內(nèi)存釋放。所以,回收干凈頁(yè)的方式是直接釋放內(nèi)存,回收臟頁(yè)的方式是先寫(xiě)回磁盤(pán)后再釋放內(nèi)存。匿名頁(yè)(Anonymous Page):這部分內(nèi)存沒(méi)有實(shí)際載體,不像文件緩存有硬盤(pán)文件這樣一個(gè)載體,比如堆、棧數(shù)據(jù)等。這部分內(nèi)存很可能還要再次被訪問(wèn),所以不能直接釋放內(nèi)存,它們回收的方式是通過(guò) Linux 的 Swap 機(jī)制,Swap 會(huì)把不常訪問(wèn)的內(nèi)存先寫(xiě)到磁盤(pán)中,然后釋放這些內(nèi)存,給其他更需要的進(jìn)程使用。再次訪問(wèn)這些內(nèi)存時(shí),重新從磁盤(pán)讀入內(nèi)存。

Swap分區(qū)在系統(tǒng)的物理內(nèi)存不夠用的時(shí)候,把硬盤(pán)內(nèi)存中的一部分空間釋放出來(lái),以供當(dāng)前運(yùn)行的程序使用。那些被釋放的空間可能來(lái)自一些很長(zhǎng)時(shí)間沒(méi)有什么操作的程序,這些被釋放的空間被臨時(shí)保存到Swap分區(qū)中,等到那些程序要運(yùn)行時(shí),再?gòu)腟wap分區(qū)中恢復(fù)保存的數(shù)據(jù)到內(nèi)存中。

文件頁(yè)和匿名頁(yè)的回收都是基于 LRU 算法,也就是優(yōu)先回收不常訪問(wèn)的內(nèi)存。LRU 回收算法,實(shí)際上維護(hù)著 active 和 inactive 兩個(gè)雙向鏈表,其中:

active_list活躍內(nèi)存頁(yè)鏈表,這里存放的是最近被訪問(wèn)過(guò)(活躍)的內(nèi)存頁(yè);inactive_list不活躍內(nèi)存頁(yè)鏈表,這里存放的是很少被訪問(wèn)(非活躍)的內(nèi)存頁(yè);

越接近鏈表尾部,就表示內(nèi)存頁(yè)越不常訪問(wèn)。在回收內(nèi)存時(shí),系統(tǒng)就可以根據(jù)活躍程度,優(yōu)先回收不活躍的內(nèi)存。

內(nèi)存回收帶來(lái)的問(wèn)題

回收內(nèi)存方式的不同。回收的內(nèi)存類型的不同會(huì)帶來(lái)不同的影響,下面我們就來(lái)學(xué)習(xí)一下不同的是否,不同的類型會(huì)帶來(lái)怎樣的影響。回收內(nèi)存方式:后臺(tái)回收:直接回收

一種是后臺(tái)內(nèi)存回收,也就是喚醒 kswapd 內(nèi)核線程,這種方式是異步回收的,不會(huì)阻塞進(jìn)程。一種是直接內(nèi)存回收,這種方式是同步回收的,會(huì)阻塞進(jìn)程,這樣就會(huì)造成很長(zhǎng)時(shí)間的延遲,以及系統(tǒng)的CPU 利用率會(huì)升高,最終引起系統(tǒng)負(fù)荷飆高。

可被回收的內(nèi)存類型:文件頁(yè)和匿名頁(yè)

文件頁(yè)的回收:對(duì)于干凈頁(yè)是直接釋放內(nèi)存,這個(gè)操作不會(huì)影響性能,而對(duì)于臟頁(yè)會(huì)先寫(xiě)回到磁盤(pán)再釋放內(nèi)存,這個(gè)操作會(huì)發(fā)生磁盤(pán) I/O的,這個(gè)操作是會(huì)影響系統(tǒng)性能的。匿名頁(yè)的回收:如果開(kāi)啟了 Swap 機(jī)制,那么 Swap 機(jī)制會(huì)將不常訪問(wèn)的匿名頁(yè)換出到磁盤(pán)中,下次訪問(wèn)時(shí),再?gòu)拇疟P(pán)換入到內(nèi)存中,這個(gè)操作是會(huì)影響系統(tǒng)性能的。

可以看到,回收內(nèi)存的操作基本都會(huì)發(fā)生磁盤(pán) I/O 的,如果回收內(nèi)存的操作很頻繁,意味著磁盤(pán) I/O 次數(shù)會(huì)很多,整個(gè)系統(tǒng)給人的感覺(jué)就是很卡。

如何降低內(nèi)存回收的影響

從文件頁(yè)和匿名頁(yè)的回收操作來(lái)看,文件頁(yè)的回收操作對(duì)系統(tǒng)的影響相比匿名頁(yè)的回收操作會(huì)少一點(diǎn),因?yàn)槲募?yè)對(duì)于干凈頁(yè)回收是不會(huì)發(fā)生磁盤(pán) I/O 的,匿名頁(yè)的 Swap 換入換出這兩個(gè)操作都會(huì)發(fā)生磁盤(pán) I/O。盡早觸發(fā) kswapd 內(nèi)核線程異步回收內(nèi)存來(lái)避免應(yīng)用程序進(jìn)行直接內(nèi)存回收。

如何保護(hù)一個(gè)進(jìn)程不被 OOM 殺掉呢?

在系統(tǒng)空閑內(nèi)存不足的情況,進(jìn)程申請(qǐng)了一個(gè)很大的內(nèi)存,如果直接內(nèi)存回收都無(wú)法回收出足夠大的空閑內(nèi)存,那么就會(huì)觸發(fā) OOM 機(jī)制,內(nèi)核就會(huì)根據(jù)算法選擇一個(gè)進(jìn)程殺掉。

Linux 到底是根據(jù)什么標(biāo)準(zhǔn)來(lái)選擇被殺的進(jìn)程呢?這就要提到一個(gè)在 Linux 內(nèi)核里有一個(gè)oom_badness()函數(shù),它會(huì)把系統(tǒng)中可以被殺掉的進(jìn)程掃描一遍,并對(duì)每個(gè)進(jìn)程打分,得分最高的進(jìn)程就會(huì)被首先殺掉。

進(jìn)程得分的結(jié)果受下面這兩個(gè)方面影響:

第一,進(jìn)程已經(jīng)使用的物理內(nèi)存頁(yè)面數(shù)。第二,每個(gè)進(jìn)程的 OOM 校準(zhǔn)值 oom_score_adj,我們可以在設(shè)置 -1000 到 1000 之間的任意一個(gè)數(shù)值,調(diào)整進(jìn)程被 OOM Kill 的幾率。

函數(shù) oom_badness() 里的最終計(jì)算方法是這樣的:

// points 代表打分的結(jié)果// process_pages 代表進(jìn)程已經(jīng)使用的物理內(nèi)存頁(yè)面數(shù)// oom_score_adj 代表 OOM 校準(zhǔn)值// totalpages 代表系統(tǒng)總的可用頁(yè)面數(shù)points = process_pages + oom_score_adj * totalpages / 1000

計(jì)算出來(lái)的值越大,那么這個(gè)進(jìn)程被 OOM Kill 的幾率也就越大。

每個(gè)進(jìn)程的 oom_score_adj默認(rèn)值都為 0,所以最終得分跟進(jìn)程自身消耗的內(nèi)存有關(guān),消耗的內(nèi)存越大越容易被殺掉。我們可以通過(guò)調(diào)整 oom_score_adj 的數(shù)值,來(lái)改成進(jìn)程的得分結(jié)果:

如果你不想某個(gè)進(jìn)程被首先殺掉,那你可以調(diào)整該進(jìn)程的 oom_score_adj,從而改變這個(gè)進(jìn)程的得分結(jié)果,降低該進(jìn)程被 OOM 殺死的概率。如果你想某個(gè)進(jìn)程無(wú)論如何都不能被殺掉,那你可以將 oom_score_adj 配置為 -1000。

我們最好將一些很重要的系統(tǒng)服務(wù)的 oom_score_adj 配置為 -1000,比如 sshd,因?yàn)檫@些系統(tǒng)服務(wù)一旦被殺掉,我們就很難再登陸進(jìn)系統(tǒng)了。

不建議將我們自己的業(yè)務(wù)程序的 oom_score_adj 設(shè)置為 -1000,因?yàn)闃I(yè)務(wù)程序一旦發(fā)生了內(nèi)存泄漏,而它又不能被殺掉,這就會(huì)導(dǎo)致隨著它的內(nèi)存開(kāi)銷(xiāo)變大,OOM killer 不停地被喚醒,從而把其他進(jìn)程一個(gè)個(gè)給殺掉。

關(guān)鍵詞:

首頁(yè)
頻道
底部
頂部