报告内存的标准文件/工具在不同的 Linux 发行版上似乎有不同的格式。例如,在 Arch 和 Ubuntu 上。
拱
$ free total used free shared buff/cache available Mem: 8169312 3870392 2648348 97884 1650572 4110336 Swap: 16777212 389588 16387624 $ head /proc/meminfo MemTotal: 8169312 kB MemFree: 2625668 kB MemAvailable: 4088520 kB Buffers: 239688 kB Cached: 1224520 kB SwapCached: 17452 kB Active: 4074548 kB Inactive: 1035716 kB Active(anon): 3247948 kB Inactive(anon): 497684 kB
乌班图
$ free total used free shared buffers cached Mem: 80642828 69076080 11566748 3063796 150688 58358264 -/+ buffers/cache: 10567128 70075700 Swap: 20971516 5828472 15143044 $ head /proc/meminfo MemTotal: 80642828 kB MemFree: 11565936 kB Buffers: 150688 kB Cached: 58358264 kB SwapCached: 2173912 kB Active: 27305364 kB Inactive: 40004480 kB Active(anon): 7584320 kB Inactive(anon): 4280400 kB Active(file): 19721044 kB
那么,我如何可移植(仅限 Linux 发行版)并可靠地获取可供我的软件在特定时间使用的内存量(不包括交换区)?据推测,这就是 Archfree
和Arch的输出中显示为“可用”和“MemAvailable”的内容,cat /proc/meminfo
但如何在 Ubuntu 或其他发行版中获得相同的结果?
答案1
MemAvailable
/proc/meminfo
自 3.14 版内核起包含;它是由提交 34e431b0a。这是您显示的输出变化的决定因素。提交消息指示如何估计可用内存而无需MemAvailable
:
目前,在不将系统推入交换的情况下,可用于新工作负载的内存量可以根据
MemFree
、Active(file)
、Inactive(file)
和SReclaimable
以及来自 的“低”水位线进行估计/proc/zoneinfo
。
低水位线是系统交换的级别。因此,在没有 的情况下,您至少可以将、和MemAvailable
给出的值相加(以中存在的为准),并从 中减去低水位线。后者还列出了每个区域的可用页面数量,这可能有助于比较......MemFree
Active(file)
Inactive(file)
SReclaimable
/proc/meminfo
/proc/zoneinfo
完整的算法在补丁中给出,meminfo.c
并且看起来相当容易适应:
- 将所有区域的低水位线相加;
- 获取已识别的空闲内存 (
MemFree
); - 减去低水印(我们需要避免触及它以避免交换);
- 添加我们可以从页面缓存使用的内存量( 和
Active(file)
)Inactive(file)
:这是页面缓存使用的内存量,减去页面缓存的一半或低水位线,以较小者为准; SReclaimable
按照相同的算法添加我们可以回收的内存量 ( )。
因此,将所有这些放在一起,您可以通过以下方式获取可用于新进程的内存:
awk -v low=$(grep low /proc/zoneinfo | awk '{k+=$2}END{print k}') \
'{a[$1]=$2}
END{
print a["MemFree:"]+a["Active(file):"]+a["Inactive(file):"]+a["SReclaimable:"]-(12*low);
}' /proc/meminfo
答案2
尽管 Stephen 的回答非常充分,并且谨慎行事,但我还是决定写下完整的逻辑,包括最低限度的比较。首先从 /proc/meminfo 读取信息并将其存储在变量中,以使内存详细信息保持一致。
LOW_WATERMARK=$(awk '$1 == "low" {LOW_WATERMARK += $2} END {print LOW_WATERMARK * 4096}' /proc/zoneinfo)
MEMINFO=$(</proc/meminfo)
MEMINFO_MEMFREE=$(echo "${MEMINFO}" | awk '$1 == "MemFree:" {print $2 * 1024}')
MEMINFO_FILE=$(echo "${MEMINFO}" | awk '{MEMINFO[$1]=$2} END {print (MEMINFO["Active(file):"] + MEMINFO["Inactive(file):"]) * 1024}')
MEMINFO_SRECLAIMABLE=$(echo "${MEMINFO}" | awk '$1 == "SReclaimable:" {print $2 * 1024}')
MEMINFO_MEMAVAILABLE=$((
MEMINFO_MEMFREE - LOW_WATERMARK
+ MEMINFO_FILE - ((MEMINFO_FILE/2) < LOW_WATERMARK ? (MEMINFO_FILE/2) : LOW_WATERMARK)
+ MEMINFO_SRECLAIMABLE - ((MEMINFO_SRECLAIMABLE/2) < LOW_WATERMARK ? (MEMINFO_SRECLAIMABLE/2) : LOW_WATERMARK)
))
if [[ "${MEMINFO_MEMAVAILABLE}" -le 0 ]]
then
MEMINFO_MEMAVAILABLE=0
fi
存储在变量中的结果以字节为单位。