並非單純殺佔用記憶體最多的進程,而是由 /proc/ 決定,經內核 oom_badness() 函數計算。核心原則:
points = p->mm->total_vm;
不包含 Swap,物理記憶體越大分越高,越易被殺。
if (chld->mm != p->mm && chld->mm)
points += chld->mm->total_vm;
防止 Fork 型服務器產生大量子進程洩漏記憶體。
s = int_sqrt(cpu_time); if (s) points /= s; s = int_sqrt(int_sqrt(run_time)); if (s) points /= s;
長期運行、高 CPU 佔用的進程分數降低,受保護。
if (task_nice(p) > 0) points *= 2;
低優先級(nice 為正)進程分數翻倍,更易被殺。
if (capable(CAP_SYS_ADMIN) || uid == 0) points /= 4; if (capable(CAP_SYS_RAWIO)) points /= 4;
Root 進程、可訪問裸設備的進程分數降低 4 倍。
if (p->oom_score_adj > 0) points <<= p->oom_score_adj; else points >>= -(p->oom_score_adj);
範圍 -1000 到 +1000(舊版 -17 到 +15),移位運算影響極大。設置 -1000 可實質免疫 OOM Killer。
編寫測試程式申請 1GB 虛擬記憶體,每 10 秒實際佔用 +100MB。在 2GB 記憶體 + 400MB Swap 機器運行 3 個實例:

設置 overcommit_memory=2 禁用過量分配雖能根治,但會導致:
Linux 設計 Overcommit 正是為平衡靈活性與風險。
MySQL 通常是系統最大記憶體消費者,默認極易成 OOM Killer 目標。下章將從 MySQL 角度分析如何規避風險。