Linux: échange total utilisé = échange utilisé par les processus +?

17

Donc, j'essaie de faire une enquête sur l'origine de l'utilisation du swap dans un système avec une utilisation élevée du swap:

# free
             total       used       free     shared    buffers     cached
Mem:        515324     508800       6524          0       4852      27576
-/+ buffers/cache:     476372      38952
Swap:       983032     503328     479704

Addition du swap utilisé par processus:

# for proc in /proc/*; do cat $proc/smaps 2>/dev/null | awk '/Swap/{swap+=$2}END{print swap "\t'`readlink $proc/exe`'"}'; done | sort -n | awk '{total+=$1}/[0-9]/;END{print total "\tTotal"}'
0       /bin/gawk
0       /bin/sort
0       /usr/bin/readlink
28      /sbin/xxxxxxxx
52      /sbin/mingetty
52      /sbin/mingetty
52      /sbin/mingetty
52      /sbin/mingetty
56      /sbin/mingetty
56      /sbin/mingetty
60      /xxxxxxxxxxx
60      /usr/sbin/xxx
84      /usr/sbin/xxx
108     /usr/bin/xxx
168     /bin/bash
220     /sbin/init
256     /sbin/rsyslogd
352     /bin/bash
356     /bin/bash
360     /usr/sbin/sshd
496     /usr/sbin/crond
672     /usr/sbin/sshd
12972   /opt/jdk1.6.0_22/bin/java
80392   /usr/libexec/mysqld
311876  /opt/jdk1.6.0_22/bin/java
408780  Total

Ce qui donne une valeur inférieure pour le swap total utilisé. Où se trouve le swapspace restant? S'agit-il de mémoire vmalloc () dans le noyau? Autre chose? Comment puis-je l'identifier?

Sortie de meminfo:

# cat /proc/meminfo 
MemTotal:       515324 kB
MemFree:          6696 kB
Buffers:          5084 kB
Cached:          28056 kB
SwapCached:     157512 kB
Active:         429372 kB
Inactive:        65068 kB
HighTotal:           0 kB
HighFree:            0 kB
LowTotal:       515324 kB
LowFree:          6696 kB
SwapTotal:      983032 kB
SwapFree:       478712 kB
Dirty:             100 kB
Writeback:           0 kB
AnonPages:      399456 kB
Mapped:           8792 kB
Slab:             7744 kB
PageTables:       1820 kB
NFS_Unstable:        0 kB
Bounce:              0 kB
CommitLimit:   1240692 kB
Committed_AS:  1743904 kB
VmallocTotal:   507896 kB
VmallocUsed:      3088 kB
VmallocChunk:   504288 kB
HugePages_Total:     0
HugePages_Free:      0
HugePages_Rsvd:      0
Hugepagesize:     4096 kB
ninj
la source
Les tampons et le cache sont inclus et ne sont associés à aucun processus.
goldilocks
2
@goldilocks: non, ceux-ci sont dans la mémoire physique. De plus, ils ne s'additionnent pas.
ninj
Vous avez raison, je suppose que mettre en cache des trucs à échanger serait en quelque sorte inutile. Cependant, je pense que les trucs qui sont échangés peuvent être laissés là et suivis même après que le processus qui leur appartient soit éteint, tant que cet espace d'échange n'est pas nécessaire autrement; cela fait gagner du temps plus tard si un processus charge la même page et que cette page doit être à nouveau échangée - elle est déjà là dans l'échange. Google "swap cache" linux-tutorial.info/modules.php?name=MContent&pageid=314 Cela correspond à la façon dont le "cache cache" est créé (il s'agit de choses enregistrées en mémoire à partir de processus désormais disparus).
goldilocks
... ce qui signifie, lol, que "mettre des trucs en cache dans le swap" n'est pas si inutile, juste qu'il n'y arrive pas en échangeant le cache de la RAM.
goldilocks
1
La réponse n'est-elle pas simplement que le noyau peut échanger, et cela n'est pas inclus dans votre traitement? En particulier, le noyau a un tas de processus "d'espace utilisateur" de nos jours ... Juste une supposition bien pensée.
iain

Réponses:

11

La différence que vous observez n'est pas due au fait que l'espace d'échange n'est pas pris en compte. Le "(supprimé)" que le noyau ajoute parfois aux /proc/*/exeliens est généré par readlinket provoque des erreurs d'analyse dans votre script awk, et vous ne comptez en fait pas les processus dont les binaires ne sont plus présents dans votre total.

Certains noyaux ajoutent le mot "(supprimé)" aux /proc/*/exeliens symboliques des cibles lorsque l'exécutable d'origine du processus n'existe plus.

La raison pour laquelle votre commande affiche moins que le total est à cause de cela. La sortie de readlinksur de tels liens sera quelque chose comme "/ chemin / vers / bin (supprimé)", ce qui provoque une erreur d'analyse awklorsque la sortie est replacée dans la chaîne (elle n'aime pas les parenthèses et les espaces). Par exemple, procédez comme suit:

for a in /proc/*/exe ; do readlink $a ; done | grep deleted

Et vous verrez quelques entrées avec "(supprimé)" en annexe. Si vous avez examiné l'utilisation du swap pour ces entrées, leur total correspondrait à l'écart que vous voyez, car les awkerreurs résultantes empêchent leurs totaux d'être calculés et inclus dans le total final.

Si vous exécutez votre commande d'origine sans rediriger stderr n'importe où, vous remarquerez probablement quelques erreurs de "constante de chaîne incontrôlable". Ces erreurs sont le résultat de ce qui précède et vous ne devriez pas les avoir ignorées.

Ignorant d'autres améliorations potentielles de votre commande d'origine, vous pouvez la modifier en supprimant le "(supprimé)", comme ceci (note |awk '{print $1}'ajoutée à la readlinksortie):

for proc in /proc/*; \
  do cat $proc/smaps 2>/dev/null | awk '/Swap/{swap+=$2}END{print swap "\t'`readlink $proc/exe|awk '{print $1}' `'" }'; \
done | sort -n | awk '{total+=$1}/[0-9]/;END{print total "\tTotal"}'

Cette utilisation de awkpour corriger la sortie de readlinkpeut casser si le nom contient des espaces - vous pouvez utiliser sedou quelle que soit la méthode que vous préférez.

Info bonus

Au fait, vous pouvez simplement utiliser smem -t. La colonne "Swap" affiche ce que vous voulez.

En ce qui concerne le calcul vous-même, vous pouvez également obtenir ces informations plus directement à partir du VmSwapchamp /proc/*/status(les smaps nécessitent une prise en charge du noyau et ne sont pas toujours disponibles), et évitez d'avoir à rediriger la sortie d'erreur en utilisant un modèle de nom de fichier approprié qui évite la erreurs pour commencer:

for proc in /proc/[0-9]*; do \
  awk '/VmSwap/ { print $2 "\t'`readlink $proc/exe | awk '{ print $1 }'`'" }' $proc/status; \
done | sort -n | awk '{ total += $1 ; print $0 } END { print total "\tTotal" }'

Si vous n'avez pas besoin du binaire réel et que vous pouvez gérer simplement le nom du processus, vous pouvez tout obtenir de status:

for a in /proc/*/status ; do \
  awk '/VmSwap|Name/ { printf $2 " " } END { print "" }' $a ; \
done | awk '{ total+=$2 ; print $0 } END { print "Total " total }'

Et enfin, si le simple fait d'avoir les PID suffit, vous pouvez tout faire avec awk:

awk '/VmSwap/ { total += $2; print $2 "\t" FILENAME } END { print total "\tTotal" }' /proc/*/status

Remarque:

Maintenant, cela ne veut pas dire qu'il n'y a pas de différences entre freeet smem(ce dernier étant le même que votre script). Il y en a beaucoup (voir, par exemple, https://www.google.com/search?q=smem+free , qui a plus qu'assez de résultats sur la première page pour répondre à vos questions sur l'utilisation de la mémoire). Mais sans un test approprié, votre situation spécifique ne peut pas être traitée.

Jason C
la source
5

Swap est également utilisé par les tmpfs si le noyau a besoin de plus de RAM gratuit ou simplement parce qu'il n'est pas utilisé pendant un certain temps ... donc toute utilisation de tmpfs peut consommer swap.

higuita
la source
1
Pourquoi le downvote? C'est absolument correct.
jlliagre