À partir de la source page_alloc.c ci-dessous, vous pouvez voir que la partie estimation du calcul est quelle proportion de la mise en cache des pages et de la mémoire de slab récupérable peut être libérée sans causer de swap. Dans les deux cas, on suppose qu'au moins la moitié (ou la marque d'eau basse de /proc/zoneinfo
si elle est plus grande) est nécessaire.
Par conséquent, la limite de toute "inexactitude" pour chacun ne peut être que comprise entre la marque d'eau basse et en supposant que toutes peuvent être libérées, ce qui n'est certainement pas vrai.
La question de savoir si la moitié (par opposition à 1/4 ou 3/4, par exemple) est une hypothèse juste dépendrait de votre système et de votre utilisation - voir le commit original
C'est erroné car le Cache inclut de la mémoire qui n'est pas libérable comme cache de page, par exemple les segments de mémoire partagée, tmpfs et ramfs, et il n'inclut pas la mémoire de slab récupérable, qui peut occuper une grande partie de la mémoire système sur des systèmes principalement inactifs avec beaucoup de fichiers.
Dans cette question Unix & Linux, Comment puis-je obtenir la quantité de mémoire disponible de manière portable entre les distributions?, les commentaires indiquent que le calcul donne des valeurs plus élevées que la lecture de /proc/meminfo
, mais cela n'est pas toujours vrai.
long si_mem_available(void)
{
long disponible;
unsigned long cache_pages;
unsigned long wmark_bas = 0;
unsigned long pages[NR_LRU_LISTS];
unsigned long récupérable;
struct zone *zone;
int lru;
for (lru = LRU_BASE; lru < NR_LRU_LISTS; lru++)
pages[lru] = global_node_page_state(NR_LRU_BASE + lru);
for_each_zone(zone)
wmark_bas += low_wmark_pages(zone);
/*
* Estimer la quantité de mémoire disponible pour les allocations dans l'espace utilisateur,
* sans provoquer de swap.
*/
disponible = global_zone_page_state(NR_FREE_PAGES) - totalreserve_pages;
/*
* Toute la mise en cache des pages ne peut pas être libérée, sinon le système
* commencera à échanger. Supposons qu'au moins la moitié de la mise en cache des pages, ou le
* cache de valeur basse, doit rester.
*/
cache_pages = pages[LRU_ACTIVE_FILE] + pages[LRU_INACTIVE_FILE];
cache_pages -= min(cache_pages / 2, wmark_bas);
disponible += cache_pages;
/*
* Une partie des pages de la slab récupérable et d'autres parties de la mémoire
* noyau consistent en éléments qui sont utilisés et ne peuvent pas être libérés.
* Plafonnez cette estimation à la marque d'eau basse.
*/
récupérable = global_node_page_state(NR_SLAB_RECLAIMABLE) +
global_node_page_state(NR_KERNEL_MISC_RECLAIMABLE);
disponible += récupérable - min(récupérable / 2, wmark_bas);
if (disponible < 0)
disponible = 0;
return disponible;
}
EXPORT_SYMBOL_GPL(si_mem_available);