系統(tǒng)之家 - 系統(tǒng)光盤下載網站!

當前位置:系統(tǒng)之家 > 系統(tǒng)教程 > Linux OOM killer 機制

Linux如何使用OOM killer 機制?

時間:2015-08-06 11:44:48 作者:zhijie 來源:系統(tǒng)之家 1. 掃描二維碼隨時看資訊 2. 請使用手機瀏覽器訪問: https://m.xitongzhijia.net/xtjc/20150806/54848.html 手機查看 評論

  OOM killer 機制就是Linux殺死進程的以個機制,如果進程損壞系統(tǒng)資源到底某種程度,OOM killer 機制就會強制殺死進程。本文就來介紹一下Linux如何使用OOM killer 機制。

Linux如何使用OOM killer 機制?

  簡單來說該機制會監(jiān)控那些占用內存過大,尤其是瞬間很快消耗大量內存的進程,為了防止內存耗盡而內核會把該進程殺掉。

  這個功能即使在無法釋放內存的情況下,也能夠重復進行確保內存的處理過程,防止系統(tǒng)停滯,還可以找出過度消耗內存的進程。

  典型的情況是:某天一臺機器突然ssh遠程登錄不了,但能ping通,說明不是網絡的故障或者機器down掉,很大可能是sshd進程被 OOM killer殺掉了。

  重啟機器后查看系統(tǒng)日志/var/log/messages會發(fā)現(xiàn) Out of Memory: Kill process 247(sshd)類似的錯誤信息。

  還有另外一種情況也會導致能ping不能ssh,就是網絡連接過多把系統(tǒng)文件描述符資源耗盡,這里暫時不考慮這種情況。

  而在使用vip的高可用方案中,這種情況也很容易出現(xiàn)腦裂的現(xiàn)象。

  防止重要的系統(tǒng)進程觸發(fā)(OOM)機制而被殺死:可以設置參數(shù)/proc/PID/oom_adj為-17,可臨時關閉linux內核的OOM機制。內核會通過特定的算法給每個進程計算一個分數(shù)來決定殺哪個進程,每個進程的oom分數(shù)可以/proc/PID/oom_score中找到。

  我們認為重要的進程有sshd,或者一些監(jiān)控守護進程,大家可以根據(jù)自己實際情況選擇需要保護的進程。

  保護某個進程不被內核殺掉可以這樣操作:

  echo -17 》 /proc/$PID/oom_adj

  可以寫一個簡單的腳本,部署在crontab上防止重要進程被oom

  pgrep -f “/usr/sbin/sshd” | while read PID;do echo -17 》 /proc/$PID/oom_adj;done

  其中的“/usr/sbin/sshd”可以替換為你認為重要的進程,不過在匹配時候注意不要匹配錯了

  1.進程的選定方法

  OOM Killer在內存耗盡時,會查看所有進程,并分別為每個進程計算分數(shù)。將信號發(fā)送給分數(shù)最高的進程。

  2.計算分數(shù)的方法

  OOM Killer計算分數(shù)

  1. 首先,計算分數(shù)時是以進程的虛擬內存大小為基準的,虛擬內存大小可以使用ps命令的VSZ或/proc/《PID》/status的 VmSize來確認。對于正在消耗虛擬內存的進程,其最初的得分較高,單位是將1KB作為1個得分,消耗1GB內存的進程,得分約為1024*1024。

  2.如果進程正在執(zhí)行swapoff系統(tǒng)調用,則得分設置為最大值(unsigned long的最大值)。這是因為禁用swap的行為與消除內存不足是相反的,會立刻將其作為OOM Killer的對象進程。

  3.如果是母進程,則將所有子進程內存大小的一半作為分數(shù)。

  4. 根據(jù)進程的CPU使用時間和進程啟動時間調整得分,這是因為在這里認為越是長時間運行或從事越多工作的進程越重要,需保持得分較低。

  5.對于通過nice命令等將優(yōu)先級設置得較低的進程,要將得分翻倍。nice-n中設置為1~19的命令的得分翻倍。

  6.特權進程普遍較為重要,因此將其得分設置為1/4。

  7.通過capset(3)等設置了功能(capability)CAP_SYS_RAWIO注3的進程,其得分為1/4,將直接對硬件進行操作的進程判斷為重要進程。

  8.關于Cgroup,如果進程只允許與促使OOM Killer運行的進程所允許的內存節(jié)點完全不同的內存節(jié)點,則其得分為1/8。

  9.最后通過proc文件系統(tǒng)oom_adj的值調整得分。

  依據(jù)以上規(guī)則,為所有進程打分,向得分最高的進程發(fā)送信號SIGKILL(到Linux 2.6.10為止,在設置了功能CAP_SYS_RAWIO的情況下,發(fā)送SIGTERM,在沒有設置的情況下,發(fā)送SIGKILL)。

  各進程的得分可以使用/proc/《PID》/oom_score來確認。

  但是init(PID為1的)進程不能成為OOM Killer的對象。當成為對象的進程包含子進程時,先向其子進程發(fā)送信號。

  向成為對象的進程發(fā)送信號后,對于引用系統(tǒng)的全線程,即使線程組(TGID)不同,如果存在與對象進程共享相同內存空間的進程,則也向這些進程發(fā)送信號。

  至于為什么用-17而不用其他數(shù)值(默認值為0),這個是由linux內核定義的,查看內核源碼可知:

  以linux- 3.3.6版本的kernel源碼為例,路徑為linux-3.6.6/include/linux/oom.h,閱讀內核源碼可知oom_adj的可調 值為15到-16,其中15最大-16最小,-17為禁止使用OOM。oom_score為2的n次方計算出來的,其中n就是進程的oom_adj值,所 以oom_score的分數(shù)越高就越會被內核優(yōu)先殺掉。

  當然還可以通過修改內核參數(shù)禁止OOM機制

  # sysctl -w vm.panic_on_oom=1

  vm.panic_on_oom = 1 //1表示關閉,默認為0表示開啟OOM

  # sysctl -p

  測試程序

  命令行參數(shù)輸入占用內存大小N,根據(jù)自身實驗環(huán)境的物理內存大小來設置,例如我的實驗環(huán)境為內存4G,設為4G就足夠了

  代碼命名為mem.c,編譯方法 gcc -o mem mem.c

  #include 《stdio.h》

  #include 《stdlib.h》

  #include 《string.h》

  #define PAGE_SZ (1《《12)

  int main(int argc, char* argv[]) {

  int i;

  if (argc != 2) return 0;

  int gb = atoi(argv[1]);

  for (i = 0; i 《 ((unsigned long)gb《《30)/PAGE_SZ ; ++i) {

  void *m = malloc(PAGE_SZ);

  if (!m)

  break;

  memset(m, 0, 1);

  }

  printf(“allocated %lu MB\n”, ((unsigned long)i*PAGE_SZ)》》20);

  getchar();

  return 0;

  }

  然后執(zhí)行 。/mem 4

  如果不執(zhí)行任何操作的話,直接運行結果會發(fā)現(xiàn)系統(tǒng)自動oom掉這個進程

  如果我們進行以下操作,把進程優(yōu)先級設置為-17

  pgrep -f “mem” | while read PID; do echo -17 》 /proc/$PID/oom_adj;done

  你會發(fā)現(xiàn)系統(tǒng)不會把這個占用大內存的進程oom掉,但這時你也會發(fā)現(xiàn)系統(tǒng)響應變慢甚至宕機!

  設置任意進程觸發(fā)oom

  一個最簡單的測試觸發(fā)OOM的方法,可以把某個進程的oom_adj設置到15(最大值),最容易觸發(fā)。然后執(zhí)行以下命令:

  echo f 》 /proc/sysrq-trigger

  以上就是Linux如何使用OOM killer 機制,Linux強制殺死進程就不會出現(xiàn)死機或者中毒的現(xiàn)象,這是Linux一大優(yōu)點。

標簽 進程

發(fā)表評論

0

沒有更多評論了

評論就這些咯,讓大家也知道你的獨特見解

立即評論

以上留言僅代表用戶個人觀點,不代表系統(tǒng)之家立場

其他版本軟件

熱門教程

人氣教程排行

Linux系統(tǒng)推薦

掃碼關注
掃碼關注

掃碼關注 官方交流群 軟件收錄