熱搜:win11繞過硬件限制安裝 一鍵重裝Win10系統(tǒng) 最干凈的u盤啟動盤 真正純凈版的win7系統(tǒng)
時間: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 機制。
簡單來說該機制會監(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)之家立場