Linux: intercambio total utilizado = intercambio utilizado por procesos +?

17

Por lo tanto, estoy tratando de investigar un poco de dónde proviene el uso de intercambio en un sistema con alto uso de intercambio:

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

Sumar el intercambio utilizado por proceso:

# 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

Lo que da un valor más bajo para el intercambio total utilizado. ¿Dónde está el espacio de intercambio utilizado restante? ¿Es vmalloc () 'ed memoria dentro del núcleo? ¿Algo más? ¿Cómo puedo identificarlo?

Salida 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
fuente
Las memorias intermedias y la memoria caché están incluidas y no están asociadas a ningún proceso.
Ricitos de Oro
2
@goldilocks: no, esos están en la memoria física. Además, no cuadran.
ninj
Tienes razón, supongo que el almacenamiento en caché de cosas para intercambiar sería inútil. Sin embargo, creo que las cosas que se intercambian pueden dejarse allí y rastrearse incluso después de que el proceso que posee esté desactivado, siempre que ese espacio de intercambio no sea necesario; esto ahorra tiempo más adelante si un proceso carga la misma página y luego esa página debe cambiarse nuevamente, ya está allí en el intercambio. Google "swap cache" linux-tutorial.info/modules.php?name=MContent&pageid=314 Esto es paralelo a la forma en que el "caché de caché" real es (son cosas guardadas en la memoria de procesos ahora inactivos).
Ricitos de Oro
... lo que significa, jajaja, que "almacenar cosas en caché en el intercambio" no es tan inútil, solo que no llega allí cambiando el caché de RAM.
Ricitos de Oro
1
¿No es la respuesta solo que el núcleo puede intercambiarse, y eso no está incluido en su procesamiento? Particularmente, el núcleo tiene un montón de procesos de "espacio de usuario" hoy en día ... Solo una suposición considerada.
iain

Respuestas:

11

La diferencia que está observando no se debe realmente a que no se tenga en cuenta el espacio de intercambio. El "(eliminado)" que el kernel a veces agrega a los /proc/*/exeenlaces se genera readlinky está causando errores de análisis en su script awk, y efectivamente no está contando los procesos cuyos binarios ya no están presentes en su total.

Algunos núcleos añaden la palabra "(eliminado)" a los /proc/*/exedestinos de enlaces simbólicos cuando el ejecutable original para el proceso ya no existe.

La razón por la cual su comando muestra menos que el total es por esto. La salida de readlinkdichos enlaces será algo así como "/ ruta / a / bin (eliminado)", lo que provoca un error de análisis awkcuando la salida se sustituye de nuevo en la cadena (no le gustan los paréntesis y los espacios). Por ejemplo, haz esto:

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

Y verá algunas entradas con "(eliminado)" adjunto. Si observa el uso de intercambio para estas entradas, su total coincidiría con la discrepancia que ve, ya que los awkerrores resultantes evitan que sus totales se calculen e incluyan en el total final.

Si ejecuta su comando original sin redirigir stderr a ningún lado, probablemente notará algunos errores de "constante de cadena fuera de control". Esos errores son el resultado de lo anterior y no debería haberlos ignorado.

Ignorando otras posibles mejoras a su comando original, puede modificarlo eliminando el "(eliminado)", de esta manera (nota |awk '{print $1}'agregada a la readlinksalida):

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"}'

Este uso de awkpara corregir la salida de readlinkpuede romperse si el nombre contiene espacios; puede usar sedo el método que prefiera.

Información de bonificación

Por cierto, podrías usarlo smem -t. La columna "Intercambiar" muestra lo que desea.

Sin embargo, en cuanto a calcularlo usted mismo, también puede obtener esta información más directamente del VmSwapcampo en /proc/*/status(smaps requiere un poco de soporte del núcleo y no siempre está disponible), y evitar tener que redirigir la salida de error mediante el uso de un patrón de nombre de archivo adecuado que evite errores para comenzar:

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 no necesita el binario real y puede lidiar con solo tener el nombre del proceso, puede obtener todo 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 }'

Y, por último, si basta con tener los PID, puede hacerlo todo con awk:

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

Nota:

Ahora, esto no quiere decir que no haya diferencias entre freey smem(este último es el mismo que el script). Hay muchos (consulte, por ejemplo, https://www.google.com/search?q=smem+free , que tiene resultados más que suficientes en la primera página para responder sus preguntas sobre el uso de la memoria). Pero sin una prueba adecuada, su situación específica no puede abordarse.

Jason C
fuente
5

Los tmpfs también usan el intercambio si el núcleo necesita más memoria RAM libre o simplemente porque no se usa por algún tiempo ... por lo que cualquier uso de tmpfs podría consumir el intercambio.

higuita
fuente
1
¿Por qué el voto negativo? Esto es absolutamente correcto.
jlliagre