精品国产人成在线_亚洲高清无码在线观看_国产在线视频国产永久2021_国产AV综合第一页一个的一区免费影院黑人_最近中文字幕MV高清在线视频

0
  • 聊天消息
  • 系統消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發帖/加入社區
會員中心
創作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內不再提示

什么是OOM機制?怎么防止進程因為OOM機制而被殺掉?

CPP開發者 ? 來源:Linux內核那些事 ? 2023-02-06 11:45 ? 次閱讀

有時候我們會發現系統中某個進程會突然掛掉,通過查看系統日志發現是由于OOM機制導致進程被殺掉。

今天我們就來介紹一下什么是OOM機制以及怎么防止進程因為OOM機制而被殺掉。

什么是OOM機制

OOM是 Out Of Memory 的縮寫,中文意思是內存不足。而OOM機制是指當系統內存不足時,系統觸發的應急機制。

Linux 內核發現系統中的物理內存不足時,首先會對系統中的可回收內存進行回收,能夠被回收的內存有如下:

讀寫文件時的頁緩存。

為了性能而延遲釋放的空閑 slab 內存頁。

當系統內存不足時,內核會優先釋放這些內存頁。因為使用這些內存頁只是為了提升系統的性能,釋放這些內存頁也不會影響系統的正常運行。

如果釋放上述的內存后,還不能解決內存不足的情況,那么內核會如何處理呢?答案就是:觸發OOM killer殺掉系統中占用內存最大的進程。如下圖所示:

5f40b53c-a3bd-11ed-bfe3-dac502259ad0.png

可以看出,OOM killer 是防止系統崩潰的最后一個手段,不到迫不得已的情況是不會觸發的。

OOM killer 實現

接下來,我們分析一下內核是如何實現 OOM killer 的。

由于在 Linux 系統中,進程申請的都是虛擬內存地址。所以當程序調用malloc()申請內存時,如果虛擬內存空間足夠的話,是不會觸發 OOM 機制的。

當進程訪問虛擬內存地址時,如果此虛擬內存地址還沒有映射到物理內存地址的話,那么將會觸發缺頁異常。

在缺頁異常處理例程中,將會申請新的物理內存頁,并且將進程的虛擬內存地址映射到剛申請的物理內存。

如果在申請物理內存時,系統中的物理內存不足,那么內核將會回收一些能夠被回收的文件頁緩存。如果回收完后,物理內存還是不足的話,那么將會觸發swapping機制(如果開啟了的話)。

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

如果通過上面的手段還不能解決內存不足的情況,那么內核將會調用pagefault_out_of_memory()函數來殺掉系統中占用物理內存最多的進程。

我們來看看pagefault_out_of_memory()函數的實現:

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

可以看出,pagefault_out_of_memory()函數最終會調用out_of_memory()來殺死系統中占用內存最多的進程。

我們繼續來看看out_of_memory()函數的實現:

voidout_of_memory(structzonelist*zonelist,gfp_tgfp_mask,intorder,
nodemask_t*nodemask,boolforce_kill)
{
...

//1.從系統中選擇一個最壞(占用內存最多)的進程
p=select_bad_process(&points,totalpages,mpol_mask,force_kill);
...

//2.如果找到最壞的進程,那么調用oom_kill_process函數殺掉進程
if(p!=(void*)-1UL){
oom_kill_process(p,gfp_mask,order,points,totalpages,NULL,
nodemask,"Outofmemory");
killed=1;
}
...
}

out_of_memory()函數的邏輯比較簡單,主要完成兩個事情:

調用select_bad_process()函數從系統中選擇一個最壞(占用物理內存最多)的進程。

如果找到最壞的進程,那么調用oom_kill_process()函數將此進程殺掉。

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

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

staticstructtask_struct*
select_bad_process(unsignedint*ppoints,unsignedlongtotalpages,
constnodemask_t*nodemask,boolforce_kill)
{
structtask_struct*g,*p;
structtask_struct*chosen=NULL;
unsignedlongchosen_points=0;
...

//1.遍歷系統中所有的進程和線程
for_each_process_thread(g,p){
unsignedintpoints;
...

//2.計算進程最壞分數值,選擇分數最大的進程作為殺掉的目標進程
points=oom_badness(p,NULL,nodemask,totalpages);
if(!points||points

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

遍歷系統中所有的進程和線程,并且調用oom_badness()函數計算進程的最壞分數值。

選擇最壞分數值最大的進程作為被殺掉的目標進程。

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

unsignedlong
oom_badness(structtask_struct*p,structmem_cgroup*memcg,
constnodemask_t*nodemask,unsignedlongtotalpages)
{
longpoints;
longadj;

//1.如果進程不能被殺掉(init進程和內核進程是不能被殺的)
if(oom_unkillable_task(p,memcg,nodemask))
return0;
...

//2.我們可以通過/proc/{pid}/oom_score_adj文件來設置進程的被殺建議值,
//這個值越小,進程被殺的機會越低。如果設置為-1000時,進程將被禁止殺掉。
adj=(long)p->signal->oom_score_adj;
if(adj==OOM_SCORE_ADJ_MIN){
...
return0;
}

//3.統計進程使用的物理內存數
points=get_mm_rss(p->mm)
+atomic_long_read(&p->mm->nr_ptes)
+get_mm_counter(p->mm,MM_SWAPENTS);
...

//4.加上進程被殺建議值,得出最終的分數值
adj*=totalpages/1000;
points+=adj;

returnpoints>0?points:1;
}

oom_badness()函數主要按照以下步驟來計算進程的最壞分數值:

如果進程不能被殺掉(init進程和內核進程是不能被殺的),那么返回分數值為 0。

可以通過/proc/{pid}/oom_score_adj文件來設置進程的 OOM 建議值(取值范圍為 -1000 ~ 1000)。建議值越小,進程被殺的機會越低。如果將其設置為 -1000 時,進程將被禁止殺掉。

統計進程使用的物理內存數,包括實際使用的物理內存、頁表占用的物理內存和 swap 機制占用的物理內存。

最后加上進程的 OOM 建議值,得出最終的分數值。

通過oom_badness()函數計算出進程的最壞分數值后,系統就能從中選擇一個分數值最大的進程殺死,從而解決內存不足的情況。

禁止進程被 OOM 殺掉

有時候,我們不希望某些進程被 OOM killer 殺掉。例如 MySQL 進程如果被 OOM killer 殺掉的話,那么可能導致數據丟失的情況。

那么如何防止進程被 OOM killer 殺掉呢?從上面的分析可知,在內核計算進程最壞分數值時,會加上進程的oom_score_adj(OOM建議值)值。如果將此值設置為-1000時,那么系統將會禁止 OOM killer 殺死此進程。

例如使用如下命令,將會禁止殺死 PID 為 2000 的進程:

$echo-1000>/proc/2000/oom_score_adj

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







審核編輯:劉清

聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網站授權轉載。文章觀點僅代表作者本人,不代表電子發燒友網立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規問題,請聯系本站處理。 舉報投訴
  • PID
    PID
    +關注

    關注

    35

    文章

    1471

    瀏覽量

    85289
  • MySQL
    +關注

    關注

    1

    文章

    802

    瀏覽量

    26445
  • LINUX內核
    +關注

    關注

    1

    文章

    316

    瀏覽量

    21618

原文標題:細說:Linux Out Of Memory 機制

文章出處:【微信號:CPP開發者,微信公眾號:CPP開發者】歡迎添加關注!文章轉載請注明出處。

收藏 人收藏

    評論

    相關推薦

    容器JVM內存配置最佳實踐

    Killer)機制,此時系統會終止內存占用較多的進程以保證系統的正常運行。特別是在容器環境下,不合理的JVM堆參數設置會導致各種異常現象產生,例如應用堆大小還未到達JVM設置的堆閾值或應用的規格限制,就因為
    發表于 06-20 09:45 ?859次閱讀
    容器JVM內存配置最佳實踐

    怎么才能避免SD卡頻繁讀寫防止死機機制

    怎么才能避免SD卡頻繁讀寫防止死機機制
    發表于 10-23 08:14

    linux內核oom機制分析

    Linux 內核有個機制OOM killer(Out-Of-Memory killer),該機制會監控那些占用內存過大,尤其是瞬間很快消耗大量內存的進程,為了
    發表于 11-13 17:01 ?1285次閱讀
    linux內核<b class='flag-5'>oom</b><b class='flag-5'>機制</b>分析

    一個線上服務OOM的問題分享

    大家都知道,如果出現了線上OOM問題,為了不影響用戶的正常使用,最快的解決辦法就是重啟服務。
    的頭像 發表于 10-24 10:47 ?894次閱讀

    OOM Killer機制學習

    當系統內存不足以分配時,Linux內核會使用一種OOM Killer(Out-Of-Memory Killer)機制釋放內存,該機制通過一系列比較選擇出最適合的進程并將其kill掉,從
    的頭像 發表于 12-19 16:17 ?1124次閱讀

    細說Linux Out Of Memory機制

    有時候我們會發現系統中某個進程會突然掛掉,通過查看系統日志發現是由于 OOM機制 導致進程被殺掉
    的頭像 發表于 02-12 09:57 ?901次閱讀

    一圖解析K8S OOM和CPU節流

    使用 Kubernetes 時,內存不足 (OOM) 錯誤和 CPU 節流是云應用程序中資源處理的主要難題。
    的頭像 發表于 02-15 17:17 ?1280次閱讀

    SpringBoot實現MySQL百萬級數據量導出并避免OOM的解決方案

    全量加載不可行,那我們的目標就是如何實現數據的分批加載了。實事上,Mysql本身支持Stream查詢,我們可以通過Stream流獲取數據,然后將數據逐條刷入到文件中,每次刷入文件后再從內存中移除這條數據,從而避免OOM
    的頭像 發表于 03-16 13:50 ?2448次閱讀

    什么是OOM機制?怎么防止進程因為OOM機制被殺掉

    有時候我們會發現系統中某個進程會突然掛掉,通過查看系統日志發現是由于 OOM機制 導致進程被殺掉
    的頭像 發表于 06-21 08:59 ?7952次閱讀
    什么是<b class='flag-5'>OOM</b><b class='flag-5'>機制</b>?怎么<b class='flag-5'>防止</b><b class='flag-5'>進程</b><b class='flag-5'>因為</b><b class='flag-5'>OOM</b><b class='flag-5'>機制</b><b class='flag-5'>而</b><b class='flag-5'>被殺掉</b>?

    進程間通信的機制有哪些

    通信比較難,Linux內核提供了多種進程間通信的機制。 同一個進程的不同模塊(譬如不同的函數)之間進行通信都是很簡單的,譬如使用全局變量等。 通常情況下,大部分的程序是不要考慮進程間通
    的頭像 發表于 07-21 11:23 ?900次閱讀
    <b class='flag-5'>進程</b>間通信的<b class='flag-5'>機制</b>有哪些

    OOM會導致JVM虛擬機退出嗎

    熟悉Java開發的人,應該會經常遇到的異常:OOM,那么這個異常會導致 JVM 虛擬機退出嗎? 1、結論 Java虛擬機(JVM)在運行Java應用時,可能會遇到內存不足的情況,從而拋出
    的頭像 發表于 09-30 10:14 ?764次閱讀

    jvm哪些區域會發生oom

    of Memory,OOM),本文將詳細介紹 JVM 內容可能發生 OOM 的區域。OOM 是指應用程序在申請分配內存時,沒有足夠的內存供其使用,導致程序無法正常執行。 堆(Heap)區域: 堆是 JVM 中最大的一塊內存區域
    的頭像 發表于 12-05 11:51 ?1359次閱讀

    Java oom異常的原因分析

    據,棧內存用于存儲方法調用和局部變量。 當程序需要使用更多內存時,會向操作系統請求更多的內存空間。如果操作系統無法分配足夠的內存空間,就會導致OOM異常的發生。 導致OOM異常的原因有多種,下面將詳細介紹一些常見的原因。 內存
    的頭像 發表于 12-05 13:43 ?748次閱讀

    oom異常的原因和解決方法

    一、OOM異常的原因 OOM異常的出現通常是由于以下幾個原因造成的: 1.1 內存泄漏 內存泄漏是指資源在使用完畢后沒有被正確釋放或回收,從而導致內存不斷占用的現象。常見的內存泄漏問題包括對象未被
    的頭像 發表于 12-05 13:45 ?6377次閱讀

    Java怎么排查oom異常

    Java中的OOM(Out of Memory)異常是指當Java虛擬機的堆內存不足以容納新的對象時拋出的異常。OOM異常是一種常見的運行時異常,經常出現在長時間運行的Java應用程序或處理大數
    的頭像 發表于 12-05 13:47 ?1214次閱讀