Linux: Общий объем использованного обмена = обмен, используемый процессами +?

17

Итак, я пытаюсь провести некоторое исследование того, откуда происходит использование свопа в системе с высоким уровнем использования свопа:

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

Добавление свопа, используемого для процесса:

# 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

Что дает меньшее значение для общего объема использованного свопа. Где находится оставшееся используемое пространство подкачки? Это память vmalloc () внутри ядра? Что-то другое? Как я могу это определить?

Вывод 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
источник
Буферы и кеш включены и не связаны ни с каким процессом.
Златовласка
2
@goldilocks: нет, это в физической памяти. Кроме того, они не складываются.
ниндзя
Вы правы, я думаю, что кэширование чего-либо для обмена было бы бессмысленно. Тем не менее, я думаю, что выгруженный материал может быть оставлен там и отслежен даже после того, как принадлежащий ему процесс перестал существовать, если только это пространство подкачки не требуется; это экономит время позже, если процесс загружает ту же страницу, а затем эта страница должна быть заменена снова - она ​​все еще там в swap. Google "swap cache" linux-tutorial.info/modules.php?name=MContent&pageid=314 Это соответствует тому, как выглядит фактический "кеш кеша" (это вещи, сохраненные в памяти от ныне несуществующих процессов).
Златовласка
... это означает, что "кэширование в swap" не так уж и бессмысленно, просто оно не может быть достигнуто путем замены кеша RAM.
Златовласка
1
Разве ответ не в том, что ядро ​​может поменяться, и это не входит в вашу обработку? В частности, ядро ​​имеет целую кучу процессов "пространства пользователя" в настоящее время ... Просто обдуманное предположение.
13

Ответы:

11

Разница, которую вы наблюдаете, на самом деле не связана с отсутствием места подкачки. «(Удаленное)», которое ядро ​​иногда добавляет к /proc/*/exeссылкам, выводится readlinkи вызывает ошибки синтаксического анализа в вашем скрипте awk, и вы фактически не учитываете процессы, двоичные файлы которых больше не присутствуют в вашем общем объеме .

Некоторые ядра добавляют слово «(удалено)» к /proc/*/exeсимволическим ссылкам, когда исходный исполняемый файл для процесса больше не существует.

Из-за этого ваша команда показывает меньше, чем общее количество. Вывод readlinkтаких ссылок будет выглядеть примерно так: «/ path / to / bin (удалено)», что приводит к ошибке разбора, awkкогда вывод подставляется обратно в строку (ему не нравятся скобки и пробелы). Например, сделайте это:

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

И вы увидите несколько записей с добавленным «(удалено)». Если вы посмотрите на использование свопа для этих записей, их итоговое значение будет соответствовать расхождению, которое вы видите, поскольку возникающие awkошибки не позволяют рассчитать их итоговые значения и включить в итоговую итоговую сумму.

Если вы запустите свою исходную команду, нигде не перенаправляя stderr, вы, вероятно, заметите несколько ошибок «константы убегающей строки». Эти ошибки являются результатом вышесказанного, и вы не должны были их игнорировать.

Игнорируя другие потенциальные улучшения вашей исходной команды, вы можете изменить ее, удалив «(удалено)», например так (примечание |awk '{print $1}'добавлено к readlinkвыводу):

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

Это использование awkдля исправления вывода readlinkможет прерваться, если имя содержит пробелы - вы можете использовать sedлюбой другой метод, который вы предпочитаете.

Бонус Инфо

Кстати, вы могли бы просто использовать smem -t. В столбце «Обмен» отображается то, что вы хотите.

Что касается его вычисления самостоятельно, однако, вы также можете получить эту информацию более непосредственно из VmSwapполя в /proc/*/status(smaps требует поддержки ядра и не всегда доступны), и избежать необходимости перенаправлять вывод ошибок, используя правильный шаблон имени файла, который избегает ошибки для начала:

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

Если вам не нужен настоящий двоичный файл и вы можете иметь дело только с именем процесса, вы можете получить все из 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 }'

И, наконец, если достаточно иметь PID, вы можете сделать все это с помощью awk:

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

Замечания:

Теперь это не означает, что между freeи нет различий smem(последнее совпадает с вашим сценарием). Их много (см., Например, https://www.google.com/search?q=smem+free , у которых более чем достаточно результатов на первой странице, чтобы ответить на ваши вопросы об использовании памяти). Но без надлежащего теста ваша конкретная ситуация не может быть решена.

Джейсон С
источник
5

Swap также используется tmpfs, если ядру нужно больше свободной памяти или просто потому, что он некоторое время не используется ... так что любое использование tmpfs может потребовать swap.

Игиты
источник
1
Почему отрицательный голос? Это абсолютно правильно.
Jlliagre