通過獲取Linux中的 /proc/stat
文件中的內容可以獲取系統內存的詳細信息:
# cat /proc/meminfo
MemTotal: 3880404 kB
MemFree: 3182248 kB
MemAvailable: 3396580 kB
Buffers: 39588 kB
Cached: 355616 kB
SwapCached: 0 kB
Active: 318708 kB
Inactive: 252380 kB
Active(anon): 176120 kB
Inactive(anon): 248 kB
Active(file): 142588 kB
Inactive(file): 252132 kB
Unevictable: 0 kB
Mlocked: 0 kB
SwapTotal: 0 kB
SwapFree: 0 kB
Dirty: 0 kB
Writeback: 0 kB
AnonPages: 175940 kB
Mapped: 54184 kB
Shmem: 488 kB
Slab: 62040 kB
SReclaimable: 48712 kB
SUnreclaim: 13328 kB
KernelStack: 2672 kB
PageTables: 6080 kB
NFS_Unstable: 0 kB
Bounce: 0 kB
WritebackTmp: 0 kB
CommitLimit: 1940200 kB
Committed_AS: 615340 kB
VmallocTotal: 34359738367 kB
VmallocUsed: 14160 kB
VmallocChunk: 34359715580 kB
HardwareCorrupted: 0 kB
AnonHugePages: 36864 kB
CmaTotal: 0 kB
CmaFree: 0 kB
HugePages_Total: 0
HugePages_Free: 0
HugePages_Rsvd: 0
HugePages_Surp: 0
Hugepagesize: 2048 kB
DirectMap4k: 53120 kB
DirectMap2M: 3092480 kB
DirectMap1G: 3145728 kB
各字段含義見下表:
指標 | 作用 |
---|---|
MemTotal | 總內存大小 |
MemFree | 空閑內存大小 |
buffers/cached | 磁盤緩存的大小 |
MemAvailable | 可用內存大小 |
SwapTotal | 可用的swap空間的總的大小。 |
SwapFree | 剩余swap空間的大小。 |
Dirty | 需要寫入磁盤的內存區大小。 |
Writeback | 正在被寫回磁盤的大小。 |
AnonPages | 未映射頁的內存大小。 |
Mapped | 設備和文件等映射的大小。 |
Slab | 內核數據結構slab的大小,可以減少申請和釋放內存帶來的消耗。 |
注Buffers 和 Cached的區別
Buffers 是指用來給塊設備做的緩沖大小,他只記錄文件系統的metadata以及 tracking in-flight pages. cached 是用來給文件做緩沖。
buffers 是值存儲目錄里面有什么內容,權限等等。 而cached直接用來記憶我們打開的文件,比如先后執行兩次命令#man X ,你就可以明顯的感覺到第二次的開打的速度快很多。 而buffers隨時都在增加,比如先后兩次使用ls /dev后,就會發現第二次執行的速度會較第一次快。 這就是buffers/chached的區別。
- 以內核態來講,
buffers
和cached
是已經被使用的,可用內存就是MemAvailable
MemUsed = MemTotal - MemFree
- 以用戶態來講,
buffers
和cached
可被分配。
free = MemFree + Buffers + Cahched
- 本着監控應用對物理內存使用情況的目的采集,計算方法:
MemUsedPrec = 100*(MemTotal - MemFree - Buffers - Cahched)/MemTotal
黑洞

/proc/meminfo
中的數據無論如何無法與
free
中的內容對應,尤其是在
used
部分。經過一番信息檢索,得出一個結論,
free
命令中的數值是按照
/proc/meminfo
中的數據,根據一定算法計算所得,並且新版舊版的
free
所輸出內容也不一致。因此按照
proc/meminfo
中的數據計算內存使用率是更加精確的。
進一步探索,會發現 Linux 存在一個內存黑洞,在某博主博客找到如下描述:
追蹤Linux系統的內存使用一直是個難題,很多人試着把能想到的各種內存消耗都加在一起,kernel text、kernel modules、buffer、cache、slab、page table、process RSS…等等,卻總是與物理內存的大小對不上,這是為什么呢?因為Linux kernel並沒有滴水不漏地統計所有的內存分配,kernel動態分配的內存中就有一部分沒有計入/proc/meminfo中。
—— 《/PROC/MEMINFO之謎》
綜上原因,計算Linux內存使用率也就沒有必要去細扣每個數值的含義了,大致了解如下內容即可:
- MemTotal:總內存大小
- MemFree: 空閑內存大小
- buffers/cached: 磁盤緩存的大小
- MemAvailable: 可用內存大小
而計算內存使用率只需按照這個方法計算:
實際可挪用的內存數: free+cache+buffer,
實際可使用的內存數: used-cache-buffer (total-free-cache-buffer)。
內存占用率:(total-available) / total * 100
C實現
同樣的, 先定義一個結構體用於存放相關數據:
struct MEM_INFO
{
unsigned int total;
unsigned int free;
unsigned int buffers;
unsigned int cached;
unsigned int swap_cached;
unsigned int swap_total;
unsigned int swap_free;
unsigned int available;
};
typedef struct MEM_INFO Mem_info;
之后定義函數,用於獲取及計算內存數據:
void get_mem_occupy (Mem_info *o)
{
FILE* fpMemInfo = fopen("/proc/meminfo", "r");
if (NULL == fpMemInfo)
{
return ;
}
int i = 0;
int value;
char name[1024];
char line[1024];
int nFiledNumber = 2;
int nMemberNumber = 5;
while (fgets(line, sizeof(line) - 1, fpMemInfo))
{
if (sscanf(line, "%s%u", name, &value) != nFiledNumber)
{
continue;
}
if (0 == strcmp(name, "MemTotal:"))
{
++i;
o->total = value;
}
else if (0 == strcmp(name, "MemFree:"))
{
++i;
o->free = value;
}
else if (0 == strcmp(name, "MemAvailable:"))
{
++i;
o->available = value;
}
else if (0 == strcmp(name, "Buffers:"))
{
++i;
o->buffers = value;
}
else if (0 == strcmp(name, "Cached:"))
{
++i;
o->cached = value;
}
if (i == nMemberNumber)
{
break;
}
}
// system("free");
// system("cat /proc/meminfo");
// printf("MemTotal : %d\n",o->total);
// printf("MemFree : %d\n",o->free);
// printf("MemAvailable : %d\n",o->available);
// printf("MemBuffers : %d\n",o->buffers);
// printf("MemCached : %d\n",o->cached);
// printf("MemSwapCached : %d\n",o->swap_cached);
// printf("MemSwapTotal : %d\n",o->swap_total);
// printf("MemSwapFree : %d\n",o->swap_free);
fclose(fpMemInfo);
}
float cal_mem_occupy(Mem_info *o)
{
return (100.0 * (o->total - o->available) / o->total);
}
最后調用即可:
Mem_info omem;
while(1)
{
// printf("-------------------- Mem occupy -------------------\n");
get_mem_occupy(&omem);
printf("Mem Usage(%): %8.4f\n", cal_mem_occupy(&omem));
printf("\n");
}