MemAvailable
è incluso in /proc/meminfo
dalla versione 3.14 del kernel; è stato aggiunto dal commit 34e431b0a. Questo è il fattore determinante nelle variazioni di output che mostri. Il messaggio di commit indica come stimare la memoria disponibile senza MemAvailable
:
Attualmente, la quantità di memoria disponibile per un nuovo carico di lavoro, senza spingere il sistema in swap, può essere stimata da
MemFree
,Active(file)
,Inactive(file)
eSReclaimable
, così come le filigrane "basse" da/proc/zoneinfo
.
I limiti minimi sono il livello al di sotto del quale il sistema eseguirà lo scambio. Quindi, in assenza di MemAvailable
puoi almeno sommare i valori dati per MemFree
, Active(file)
, Inactive(file)
e SReclaimable
(quelli presenti in /proc/meminfo
) e sottrarre i filigrane inferiori da /proc/zoneinfo
. Quest'ultimo elenca anche il numero di pagine libere per zona, che potrebbe essere utile come confronto...
L'algoritmo completo è fornito nella patch a meminfo.c
e sembra ragionevolmente facile da adattare:
- somma i limiti minimi in tutte le zone;
- prendi la memoria libera identificata (
MemFree
); - sottrarre il limite inferiore (dobbiamo evitare di toccarlo per evitare lo scambio);
- aggiungi la quantità di memoria che possiamo utilizzare dalla cache della pagina (somma di
Active(file)
eInactive(file)
):questa è la quantità di memoria utilizzata dalla cache della pagina, meno metà della cache della pagina o il limite minimo, qualunque sia il più piccolo; - aggiungi la quantità di memoria che possiamo recuperare (
SReclaimable
), seguendo lo stesso algoritmo.
Quindi, mettendo insieme tutto questo, puoi ottenere la memoria disponibile per un nuovo processo con:
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
Sebbene la risposta di Stephen sia perfettamente sufficiente e pecchi per eccesso di cautela, ho deciso di scrivere la logica completa, inclusi i confronti minimi. Le informazioni vengono prima lette da /proc/meminfo e memorizzate in una variabile in modo che i dettagli della memoria siano coerenti.
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
Il risultato memorizzato nella variabile è in byte.