Это старый пост, однако я все же позволю себе высказать свои мысли здесь.
Начиная снизу, Linux сначала делит память на страницы (обычно 4 КБ на страницу в системе x86_64). После этого создается виртуальная память, отображение которой выполняется с физической памятью с использованием MMU (модуля управления памятью).
Процессам выделяется память из области виртуальной памяти, поэтому, пожалуйста, обратите внимание, что когда вы видите / proc / meminfo, вы увидите VMalloc * в качестве сведений о виртуальной памяти.
Допустим, у вас есть процесс, который запрашивает память (скажем, 300 МБ - веб-браузер). Процессу будет выделено 300 МБ из виртуальной памяти, однако нет необходимости в том, чтобы он отображался в памяти (то есть в физической памяти). Существует концепция «Копировать при записи» для управления памятью, согласно которой, если ваши процессы фактически используют память, выделенную из виртуальной памяти (то есть выполняет некоторую запись в памяти), только тогда она отображается в физической памяти. Это помогает ядру эффективно работать в многопроцессорной среде.
Что такое кеш?
Большая часть памяти, используемая процессами, используется совместно. Допустим, библиотека glibc используется практически всеми процессами. Какой смысл хранить несколько копий glibc в памяти, когда каждый процесс может обращаться к одной и той же ячейке памяти и выполнять свою работу. Такие часто используемые ресурсы хранятся в кэше, поэтому, когда процессы требуют, они могут ссылаться на одну и ту же область памяти. Это помогает ускорить процессы, поскольку чтение glibc (и т. Д.) Снова и снова с диска может занимать много времени.
Вышесказанное относится, скажем, к разделяемым библиотекам, подобное также верно и для чтения файлов. Если вы впервые прочитаете большой файл (скажем, 100-200 МБ), это займет много времени. Однако, если вы попытаетесь сделать то же самое снова, это будет быстрее. Данные были кэшированы в памяти, и повторное чтение не было сделано для всех блоков.
Что такое буфер?
Что касается буфера, то когда процесс выполняет файловый ввод-вывод, он полагается на буфер ядра для записи данных на диск. Процессы, запрашивает ядро, чтобы сделать работу. Таким образом, от имени процесса ядро записывает данные в свой «буфер» и сообщает процессу, что запись выполнена. В асинхронном режиме ядро будет синхронизировать эти данные в буфере на диске. Таким образом, процессы полагаются на ядро, чтобы выбрать правильное время для синхронизации данных на диск, и процессы могут продолжать работать вперед. Помните, что это обычный ввод-вывод, который делают нормальные процессы. Тем не менее, специализированные процессы, которые должны подтвердить, что ввод-вывод фактически выполняется на диске, могут использовать другой механизм для выполнения ввода-вывода на диске. Некоторые из утилит с открытым исходным кодом являются libaio. Кроме того, есть способы вызвать явную синхронизацию с FD, открытыми в контексте ваших процессов,
Каковы ошибки страницы тогда?
Рассмотрим пример, когда вы запускаете процесс (скажем, веб-браузер), чей двоичный файл составляет около 300 МБ. Однако полные 300 МБ двоичного файла веб-браузера не начинают работать мгновенно. Процесс продолжает переходить от функций к функциям в своем коде. Как уже говорилось ранее, виртуальная память будет потребляться на 300 МБ, однако не вся память сопоставлена с физической памятью (резидентная RSS-память будет меньше, см. Верхний вывод). Когда выполнение кода достигает точки, для которой память фактически не отображается физически, могут возникнуть проблемы с ошибкой страницы. Ядро отобразит эту память на физическую, свяжет страницу памяти с вашим процессом. Такая ошибка на странице называется «Незначительные ошибки страницы». Точно так же, когда процесс выполняет файловый ввод / вывод, возникают основные сбои страницы.
Когда и почему происходит обмен?
Ситуация 1:
В соответствии с приведенными выше деталями, давайте рассмотрим сценарий, когда хороший объем памяти становится отображенным в памяти. И теперь запускаются процессы, которые требуют памяти. Как обсуждалось выше, ядро должно будет выполнять некоторое отображение памяти. Однако для отображения памяти недостаточно физической памяти. Теперь ядро сначала заглянет в кеш, у него будут старые страницы памяти, которые не используются. Он сбрасывает эти страницы в отдельный раздел (называемый SWAP), освобождает некоторые страницы и сопоставляет освобожденные страницы с новым поступающим запросом. Поскольку запись на диск намного медленнее, чем в твердотельной памяти, этот процесс занимает много времени, и, следовательно, наблюдается замедление.
Ситуация 2:
Допустим, вы видите много свободной памяти, доступной в системе. Даже тогда вы видите, что происходит много свопов. Возможна проблема фрагментации памяти. Рассмотрим процессы, которые требуют от ядра 50 МБ непрерывной памяти. (имейте в виду смежные). Очевидно, что ядро выделило бы страницы случайным образом различным процессам и освободило бы некоторые из них. Однако, когда нам требуется непрерывная память, она должна искать блок, который удовлетворяет потребности процессов. Если он не может получить такую память, ему придется выполнить замену некоторых старых страниц памяти, а затем выделить смежные. Даже в таких случаях своп будет происходить. Начиная с версии 2.6 и выше, такие проблемы фрагментации значительно уменьшились. Однако, если система работает в течение длительного времени, такие проблемы все еще могут возникнуть.
Посмотрите этот пример ( вывод vmstat )
2016-10-29 03:55:32 procs -----------memory---------- ---swap-- -----io---- --system-- -----cpu------
2016-10-29 03:55:32 r b swpd free buff cache si so bi bo in cs us sy id wa st
2016-10-30 03:56:04 19 23 2914752 4692144 3344908 12162628 1660 1 8803 12701 4336 37487 14 7 40 38 0
2016-10-30 03:56:34 3 20 2889296 4977580 3345316 12026752 2109 2 8445 14665 4656 36294 12 7 46 34 0
2016-10-30 03:57:04 1 11 3418868 4939716 3347804 11536356 586 4744 2547 9535 3086 24450 6 3 59 33 0 <<<-----
2016-10-30 03:57:34 3 19 3456252 5449884 3348400 11489728 3291 13371 6407 17957 2997 22556 6 4 66 24 0
2016-10-30 03:58:04 7 6 4194500 5663580 3349552 10857424 2407 12240 3824 14560 2295 18237 4 2 65 29 0
2016-10-30 03:58:34 2 16 4203036 5986864 3348908 10838492 4601 16639 7219 18808 2575 21563 6 4 60 31 0
2016-10-30 03:59:04 3 14 4205652 6059196 3348760 10821448 6624 1597 9431 4357 1750 20471 6 2 60 31 0
2016-10-30 03:59:34 2 24 4206968 6053160 3348876 10777216 5221 2067 10106 7377 1731 19161 3 3 62 32 0
2016-10-30 04:00:04 0 13 4205172 6005084 3348932 10785896 6236 1609 10330 6264 1739 20348 4 2 67 26 0
2016-10-30 04:00:34 4 11 4206420 5996396 3348976 10770220 6554 1253 10382 4896 1964 42981 10 5 58 27 0
2016-10-30 04:01:04 6 4 4177176 5878852 3348988 10825840 8682 765 10126 2716 1731 32949 8 4 69 19 0
@ 2016-10-30 03:57:04, мы видим, что свободного объема оперативной памяти по-прежнему достаточно. Однако даже тогда своп произошел. В этот момент мы проверили дерево процессов и не увидели ни одного процесса, который бы требовал такого большого объема памяти (больше, чем свободная память). Очевидным подозрением была Ситуация 2, описанная выше. Мы проверяли журналы buddyinfo и zoneinfo выше (используйте echo m> / proc / sysrq-trigger, чтобы проверить их, вывод идет в системные журналы).
Для нашей обычной системы сравнение информации о зоне выглядит следующим образом. И графики для кеша / свободной / низкой памяти также упоминаются ниже
Глядя на информацию, становится ясно, что существует фрагментация памяти в узле 0 и нормальном узле 1 (узел это машина на основе NUMA, следовательно, несколько узлов (см. Numactl для проверки информации для вашей системы)).
Фрагментация памяти также является причиной, по которой использование подкачки может увеличиваться даже при наличии свободной памяти.