九色91_成人精品一区二区三区中文字幕_国产精品久久久久一区二区三区_欧美精品久久_国产精品99久久久久久久vr_www.国产视频

Hello! 歡迎來到小浪云!


細(xì)說|Linux Out Of Memory機(jī)制


有時(shí)候我們可能會(huì)碰到系統(tǒng)中某個(gè)進(jìn)程突然掛掉的情況,查看系統(tǒng)日志后發(fā)現(xiàn)是由于系統(tǒng)的 oom(out of memory)機(jī)制 觸發(fā)導(dǎo)致的。

今天我們來討論一下 OOM機(jī)制 是什么,以及如何防止進(jìn)程因?yàn)?OOM機(jī)制 而被終止。

什么是OOM機(jī)制

OOM 是 Out Of Memory 的縮寫,意味著系統(tǒng)內(nèi)存不足。OOM機(jī)制 是指當(dāng)系統(tǒng)內(nèi)存不足時(shí),系統(tǒng)采取的應(yīng)急措施。

當(dāng) Linux 內(nèi)核發(fā)現(xiàn)系統(tǒng)中的物理內(nèi)存不足時(shí),首先會(huì)嘗試回收可回收內(nèi)存,主要包括:

  • 用于讀寫文件的頁緩存。
  • 為了性能而延遲釋放的空閑 slab 內(nèi)存頁。

內(nèi)核會(huì)優(yōu)先釋放這些內(nèi)存頁,因?yàn)樗鼈兊尼尫挪粫?huì)影響系統(tǒng)的正常運(yùn)行,只是為了提升系統(tǒng)性能。

如果釋放這些內(nèi)存后仍然不足,內(nèi)核將會(huì)采取什么措施呢?它會(huì)觸發(fā) OOM killer,殺掉占用內(nèi)存最多的進(jìn)程,以釋放更多內(nèi)存。以下是一個(gè)示意圖:

細(xì)說|Linux Out Of Memory機(jī)制

可以看出,OOM killer 是防止系統(tǒng)崩潰的最后一個(gè)手段,不到迫不得已的情況是不會(huì)觸發(fā)的。

OOM killer 實(shí)現(xiàn)

接下來,我們分析一下內(nèi)核是如何實(shí)現(xiàn) OOM killer 的。

由于在 Linux 系統(tǒng)中,進(jìn)程申請(qǐng)的都是虛擬內(nèi)存地址。所以當(dāng)程序調(diào)用 malloc() 申請(qǐng)內(nèi)存時(shí),如果虛擬內(nèi)存空間足夠的話,是不會(huì)觸發(fā) OOM 機(jī)制的。

當(dāng)進(jìn)程訪問虛擬內(nèi)存地址時(shí),如果此虛擬內(nèi)存地址還沒有映射到物理內(nèi)存地址的話,那么將會(huì)觸發(fā) 缺頁異常。

在缺頁異常處理例程中,將會(huì)申請(qǐng)新的物理內(nèi)存頁,并且將進(jìn)程的虛擬內(nèi)存地址映射到剛申請(qǐng)的物理內(nèi)存。

如果在申請(qǐng)物理內(nèi)存時(shí),系統(tǒng)中的物理內(nèi)存不足,那么內(nèi)核將會(huì)回收一些能夠被回收的文件頁緩存。如果回收完后,物理內(nèi)存還是不足的話,那么將會(huì)觸發(fā) swapping機(jī)制(如果開啟了的話)。

swapping機(jī)制 會(huì)將某些進(jìn)程不常用的內(nèi)存頁寫入到交換區(qū)(硬盤分區(qū)或文件)中,然后釋放掉這些內(nèi)存頁,從而達(dá)到緩解內(nèi)存不足的情況。

如果通過上面的手段還不能解決內(nèi)存不足的情況,那么內(nèi)核將會(huì)調(diào)用 pagefault_out_of_memory() 函數(shù)來殺掉系統(tǒng)中占用物理內(nèi)存最多的進(jìn)程。

我們來看看 pagefault_out_of_memory() 函數(shù)的實(shí)現(xiàn):

void?pagefault_out_of_memory(void) { ????... ????out_of_memory(NULL,?0,?0,?NULL,?false); ????... } 

可以看出,pagefault_out_of_memory() 函數(shù)最終會(huì)調(diào)用 out_of_memory() 來殺死系統(tǒng)中占用內(nèi)存最多的進(jìn)程。

我們繼續(xù)來看看 out_of_memory() 函數(shù)的實(shí)現(xiàn):

void?out_of_memory(struct?zonelist?*zonelist,?gfp_t?gfp_mask,?int?order, ???????????????????nodemask_t?*nodemask,?bool?force_kill) { ????...  ????//?1.?從系統(tǒng)中選擇一個(gè)最壞(占用內(nèi)存最多)的進(jìn)程 ????p?=?select_bad_process(&points,?totalpages,?mpol_mask,?force_kill); ????...  ????//?2.?如果找到最壞的進(jìn)程,那么調(diào)用?oom_kill_process?函數(shù)殺掉進(jìn)程 ????if?(p?!=?(void?*)-1UL)?{ ????????oom_kill_process(p,?gfp_mask,?order,?points,?totalpages,?NULL, ?????????????????????????nodemask,?"Out?of?memory"); ????????killed?=?1; ????} ????... } 

out_of_memory() 函數(shù)的邏輯比較簡(jiǎn)單,主要完成兩個(gè)事情:

  1. 調(diào)用 select_bad_process() 函數(shù)從系統(tǒng)中選擇一個(gè)最壞(占用物理內(nèi)存最多)的進(jìn)程。
  2. 如果找到最壞的進(jìn)程,那么調(diào)用 oom_kill_process() 函數(shù)將此進(jìn)程殺掉。

從上面的分析可知,找到最壞的進(jìn)程是 OOM killer 最為重要的事情。

那么我們來看看 select_bad_process() 函數(shù)是怎樣選擇最壞的進(jìn)程的:

static?struct?task_struct?* select_bad_process(unsigned?int?*ppoints,?unsigned?long?totalpages, ???????????????????const?nodemask_t?*nodemask,?bool?force_kill) { ????struct?task_struct?*g,?*p; ????struct?task_struct?*chosen?=?NULL; ????unsigned?long?chosen_points?=?0; ????...  ????//?1.?遍歷系統(tǒng)中所有的進(jìn)程和線程 ????for_each_process_thread(g,?p)?{ ????????unsigned?int?points; ????????...  ????????//?2.?計(jì)算進(jìn)程最壞分?jǐn)?shù)值,?選擇分?jǐn)?shù)最大的進(jìn)程作為殺掉的目標(biāo)進(jìn)程 ????????points?=?oom_badness(p,?NULL,?nodemask,?totalpages); ????????if?(!points?||?points?continue; ????????... ????????chosen?=?p; ????????chosen_points?=?points; ????} ????...  ????return?chosen; } 

select_bad_process() 函數(shù)的主要工作如下:

  1. 遍歷系統(tǒng)中所有的進(jìn)程和線程,并且調(diào)用 oom_badness() 函數(shù)計(jì)算進(jìn)程的最壞分?jǐn)?shù)值。
  2. 選擇最壞分?jǐn)?shù)值最大的進(jìn)程作為被殺掉的目標(biāo)進(jìn)程。

所以,計(jì)算進(jìn)程的最壞分?jǐn)?shù)值就是 OOM killer 的核心工作。我們接著來看看 oom_badness() 函數(shù)是怎么計(jì)算進(jìn)程的最壞分?jǐn)?shù)值的:

unsigned?long oom_badness(struct?task_struct?*p,?struct?mem_cgroup?*memcg, ????????????const?nodemask_t?*nodemask,?unsigned?long?totalpages) { ????long?points; ????long?adj;  ????//?1.?如果進(jìn)程不能被殺掉(init進(jìn)程和內(nèi)核進(jìn)程是不能被殺的) ????if?(oom_unkillable_task(p,?memcg,?nodemask)) ????????return?0; ????...  ????//?2.?我們可以通過?/proc/{pid}/oom_score_adj?文件來設(shè)置進(jìn)程的被殺建議值, ????//????這個(gè)值越小,進(jìn)程被殺的機(jī)會(huì)越低。如果設(shè)置為?-1000?時(shí),進(jìn)程將被禁止殺掉。 ????adj?=?(long)p->signal->oom_score_adj; ????if?(adj?==?OOM_SCORE_ADJ_MIN)?{ ????????... ????????return?0; ????}  ????//?3.?統(tǒng)計(jì)進(jìn)程使用的物理內(nèi)存數(shù) ????points?=?get_mm_rss(p->mm) ????????????????+?atomic_long_read(&p->mm->nr_ptes) ????????????????+?get_mm_counter(p->mm,?MM_SWAPENTS); ????...  ????//?4.?加上進(jìn)程被殺建議值,得出最終的分?jǐn)?shù)值 ????adj?*=?totalpages?/?1000; ????points?+=?adj;  ????return?points?>?0???points?:?1; } 

oom_badness() 函數(shù)主要按照以下步驟來計(jì)算進(jìn)程的最壞分?jǐn)?shù)值:

  1. 如果進(jìn)程不能被殺掉(init進(jìn)程和內(nèi)核進(jìn)程是不能被殺的),那么返回分?jǐn)?shù)值為 0。
  2. 可以通過 /proc/{pid}/oom_score_adj 文件來設(shè)置進(jìn)程的 OOM 建議值(取值范圍為 -1000 ~ 1000)。建議值越小,進(jìn)程被殺的機(jī)會(huì)越低。如果將其設(shè)置為 -1000 時(shí),進(jìn)程將被禁止殺掉。
  3. 統(tǒng)計(jì)進(jìn)程使用的物理內(nèi)存數(shù),包括實(shí)際使用的物理內(nèi)存、頁表占用的物理內(nèi)存和 swap 機(jī)制占用的物理內(nèi)存。
  4. 最后加上進(jìn)程的 OOM 建議值,得出最終的分?jǐn)?shù)值。

通過 oom_badness() 函數(shù)計(jì)算出進(jìn)程的最壞分?jǐn)?shù)值后,系統(tǒng)就能從中選擇一個(gè)分?jǐn)?shù)值最大的進(jìn)程殺死,從而解決內(nèi)存不足的情況。

禁止進(jìn)程被 OOM 殺掉

有時(shí)候,我們不希望某些進(jìn)程被 OOM killer 殺掉。例如 mysql 進(jìn)程如果被 OOM killer 殺掉的話,那么可能導(dǎo)致數(shù)據(jù)丟失的情況。

那么如何防止進(jìn)程被 OOM killer 殺掉呢?從上面的分析可知,在內(nèi)核計(jì)算進(jìn)程最壞分?jǐn)?shù)值時(shí),會(huì)加上進(jìn)程的 oom_score_adj(OOM建議值)值。如果將此值設(shè)置為 -1000 時(shí),那么系統(tǒng)將會(huì)禁止 OOM killer 殺死此進(jìn)程。

例如使用如下命令,將會(huì)禁止殺死 PID 為 2000 的進(jìn)程:

$?echo?-1000?>?/proc/2000/oom_score_adj 

這樣,我們就能防止一些重要的進(jìn)程被 OOM killer 殺死。

相關(guān)閱讀

主站蜘蛛池模板: 亚洲一区二区在线视频 | 精品日韩在线 | 久久久久久91香蕉国产 | 国产精品欧美精品日韩精品 | 91av亚洲 | 9久久婷婷国产综合精品性色 | 99精品国产一区二区青青牛奶 | 伊人久久大香线 | 99热播放 | 毛片a级| 国产一区视频在线 | 国产一区二区小视频 | 久久久久久99 | 免费久久久 | 精久久 | 91精品国产91久久综合桃花 | 91视视频在线观看入口直接观看 | 亚洲最新在线视频 | 日韩毛片在线视频 | 97人人澡人人爽91综合色 | 亚洲经典一区 | 三a毛片 | 久久久久久av | 国产免费av在线 | 草逼网站 | 国产一级一级国产 | 精品国产一区探花在线观看 | 日韩亚洲欧美综合 | 日韩精品一区二区三区在线 | 亚洲不卡在线观看 | 91精品国产综合久久福利软件 | 久久精品这里精品 | 免费看片在线播放 | 国产成人一区二区 | 久久久久中文字幕 | 国产精品五月天 | 久久久亚洲成人 | 国产一级免费视频 | 亚洲欧美日韩精品 | 精品久久久久久久久亚洲 | 成人国产精品久久 |