一、內存泄漏
內存泄漏是指程序在申請內存後,使用完畢後沒有正確歸還給系統,導致該內存一直佔據着系統的內存資源,直至系統資源被耗盡。內存泄露是導致 Out of Memory 的一個主要原因
舉個例子,當一個內存分配的應用程序申請一塊內存,如果在代碼中無法找到釋放該內存的代碼塊,則該塊內存將一直佔用內存並不釋放,最終導致系統內存不足。
char *str;
while(1){
str = (char*)malloc(1024); //申請1KB內存
printf("Allocating 1 KB... \n");
}
二、內存資源的限制
內存是有限的,不可能越來越大,因此在Linux中資源限制是必須的。在內核中有以下幾種內存資源限制:
1. RLIMIT_STACK: 進程棧空間的限制
2. RLIMIT_CORE: Core文件大小的限制
3. RLIMIT_DATA: 數據段的限制
4. RLIMIT_FSIZE: 文件大小的限制
如果進程超過了資源限制,內核將向該進程發送一個.SIGXCPU 信號通知進程超過了資源限制。
三、OOM Killer
當系統內存使用超出可用範圍時,內核必須通過停止其中一個或多個進程來釋放內存,並且選擇將哪個進程停止。此時會觸發 OOM Killer。
OOM Killer 會在操作系統內核發現內存不足時自動運行,根據系統內部的算法找到佔用內存資源最多的進程,並強制殺死該進程。其優先級低於Kswapd,但優先級比任何其他代碼都高
四、Kswapd
Kswapd是Kernel Swap Daemon的簡稱,是Linux內核內存管理機制的重要組成部分。它的主要工作是監控操作系統對存儲器的使用,當發現內存過度使用或存在大量等待空閑內存的進程時,就會觸發Swap機制,將不常用的頁調出物理內存並寫入硬盤上swap分區中,從而獲得額外的內存空間來存放正在運行的進程需要的數據。
它主要分為兩種狀態:
1. Kswapd0: 負責回收匿名內存(代價較大,優先級低)
2. Kswapd1: 負責回收頁面緩存(代價較小,優先級高)
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
int main(int argc,char* argv[]){
char* buffer = NULL;
int buffer_size = atoi(argv[1]);
memset(buffer, '0', buffer_size);
sleep(60);
return 0;
}
五、解決方案
避免 Out of Memory 的一個有效辦法是利用 Swap 空間。Swap 是指硬盤上留出的一部分空間,用來存放內存中暫時不使用的數據。當物理內存不足時就可將暫時不使用內存存放到 Swap 空間中,騰出物理內存,以保證系統正常運行。但是,如果過多使用 Swap 空間,也會導致系統性能下降。
除 Swap 外,還有以下一些解決方案:
1. 調整應用進程所佔內存空間大小,減少內存消耗(需要在進程佔用內存空間過大時及時進行升級)
2. 合理使用內存,注意申請/釋放內存資源追蹤問題
3. 部署內存監控機制,實時監控內存消耗狀況
原創文章,作者:小藍,如若轉載,請註明出處:https://www.506064.com/zh-hk/n/206882.html