Как система знает, когда файл был изменен? В особенности файлы с отображенной памятью

Различие, которое Вы наблюдаете, не происходит на самом деле из-за области подкачки, являющейся неучтенным." (Удаленный)", к которому иногда добавляет ядро /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 (снимки требуют, чтобы некоторое ядро поддерживало, и не всегда доступно), и избегите необходимости перенаправлять вывод ошибок при помощи надлежащего шаблона имени файла, который избегает ошибок для начала:

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

И наконец, просто имение PIDs достаточно, можно просто сделать все это с 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, который имеет более чем достаточно результатов на первой странице для ответа на вопросы об использовании памяти). Но без надлежащего теста, не может быть обращена Ваша определенная ситуация.

3
19.04.2014, 01:07
1 ответ

Ядро знает, какие страницы изменяются, так же, как и любые другие страницы: когда они записываются, в таблицах страниц устанавливается флаг, помечающий их как «грязные». Это делается либо ЦП, либо MMU, либо с их помощью (например, они могут установить бит напрямую или вызвать прерывание, чтобы программное обеспечение сделало это).

Но на самом деле поведение, которое вы предполагаете, не гарантируется. Измененные страницы не нужно записывать обратно (или даже ставить в очередь для обратной записи) до тех пор, пока не будет вызван msync или munmap .

Я не уверен, сколько других способов изменить файл, но их как минимум несколько:

  1. truncate / ftruncate
  2. writev , pwritev , aio_write (варианты write )
  3. Используйте его как файл подкачки, резервное устройство для устройства обратной связи (например, / dev / loop0) и т. д.
  4. Могут быть вызовы ioctl , которые изменяют содержимое файла. Хуже того, они могут зависеть от файловой системы.
3
27.01.2020, 21:23

Теги

Похожие вопросы