В продолжение
поста о команде free, посмотрим на более полный источник об использовании памяти - специальную виртуальную файловую систему /proc, являющуюся общей точкой доступа к структурам данных ядра, а именно - на информацию /proc/meminfo. Вывод команды cat:
[andrey@server1 ~]$ cat /proc/meminfo
MemTotal: 1945312 kB
MemFree: 48980 kB
Buffers: 2248 kB
Cached: 171092 kB
SwapCached: 256 kB
Active: 622380 kB
Inactive: 32504 kB
HighTotal: 1048256 kB
HighFree: 3176 kB
LowTotal: 897056 kB
LowFree: 45804 kB
SwapTotal: 2048276 kB
SwapFree: 2047868 kB
Dirty: 2696 kB
Writeback: 400 kB
AnonPages: 481592 kB
Mapped: 137244 kB
Slab: 34244 kB
PageTables: 7276 kB
NFS_Unstable: 0 kB
Bounce: 0 kB
CommitLimit: 2433156 kB
Committed_AS: 1277084 kB
VmallocTotal: 114680 kB
VmallocUsed: 14232 kB
VmallocChunk: 99948 kB
Пройдемся сверху вниз с некоторыми комментариями по части из этих значений.
MemTotal - Доступный объем оперативной памяти. Часть физически доступной памяти резервируется во время запуска системы ядром и не входит в указанный здесь объем:
[root@server1 ~]# grep Memory: /var/log/dmesg
Memory: 1941740k/1965760k available
(2097k kernel code, 22716k reserved,
877k data, 228k init, 1048256k highmem)
MemFree - Какой объем памяти не используется и доступен для немедленного выделения процессам. Ядро Linux старается использовать доступную память максимально эффективно, и, по умолчанию, достаточно большой объем ОЗУ, потенциально доступный для приложений, может быть занят под кэш и буферы. Объем свободной памяти в несколько десятков мегабайт на машинах с гигабайтами оперативной памяти - вполне типичная картина для Linux. В 32-разрядной операционной системе MemFree=LowFree+HighFree.
Buffers - область ОЗУ, занятая хранением данных, ожидающих записи на диск. Буфер позволяет приложениям продолжать выполнение своей задачи не дожидаясь момента когда данные будут физически записаны на диск. Обычно размер около 20Мб.
Cached - Объем занятый в ОЗУ под кэш чтения страниц с диска (файлы, директории, файлы блочных устройств, данные, относящиеся к механизму IPC, данные процессов уровня пользователя, сброшенных в область подкачки). Не включает в себя SwapCached.
SwapCached - Объем памяти, который однажды был помещен в область подкачки, но потом перенесен обратно в ОЗУ. Однако данные все еще присутствуют в swap, и при необходимости этот объем памяти может быть вновь освобожден без необходимости тратить ресурсы на "дорогие" операции ввода/вывода.
Active - Объем памяти, занятый в ОЗУ наиболее часто используемыми страницами памяти. Иными словами, эти страницы памяти активно используются процессами и будут освобождаться только в случае крайней необходимости.
Inactive - Объем памяти, занятый в ОЗУ не используемыми в настоящий момент страницами. Эти страницы считаются наиболее подходящими для выгрузки в swap и освобождения в случае необходимости.
High{Total,Free}, Low{Total,Free} - MemTotal=HighTotal+LowTotal. Вывод команды cat /proc/meminfo получен на 32-разрядной операционной системе. Модель использования памяти в 32-разрядном и 64-разрядном ядрах отличается. Ниже я привел рисунок, показывающий эти отличия:
В 32-р архитектуре ядро Linux может напрямую адресовать только первый гигабайт физической памяти. На рисунке ZONE_NORMAL - это и есть область памяти объемом LowTotal:897056 kB. Число меньше гигабайта за счет зарезервированных ядром областей памяти. Из оставшегося объема нужно вычесть 1Мб, используемый BIOS и устройствами ввода/вывода, а также 16Mб ZONE_DMA для совместимости с ограничениями устройств на шине ISA. Память "выше" первого гигабайта - ZONE_HIGHMEM (HighTotal:1048256 kB). Доступ к ней осуществляется через отображение на первый гигабайт ОЗУ. Отображение "прозрачно" для приложений, но вызывает небольшую потерю производительности. ZONE_NORMAL используется для тех же нужд что и зона ZONE_HIGHMEM, плюс для собственных структур ядра. В 64-разрядных архитектурах зона ZONE_HIGHMEM всегда пуста.
Swap{Total, Free} - SwapTotal - это общий объем области подкачки (как в разделе подкачки, так и в swap-файлах, если они используются). Как и в случае с ОЗУ, ядро Linux старается использовать область подкачки максимально эффективно. Иногда факт использования части области подкачки еще не означает того, что память является "узким местом" производительности системы. Один из способов влиять на агрессивность использования swap - это парметр vm.swappiness. Чем больше процент swappiness, тем активнее будет выгрузка в swap. По умолчанию в RHEL5 это число 60%. Предпочтительно использовать более агрессивную политику выгрузки в область подкачки, когда вы, например, на рабочей станции большую часть времени работаете с одним большим пакетом ПО и редко переключаетесь на другие задачи. Пример из области серверов - машина с ограниченным ОЗУ, выполняющая какие-то пакетные задания (процессы, находящиеся долгое время в состоянии S). На серверах с большим объемом ОЗУ увеличения swappiness может свести все выгоды использования swap "на нет" из-за активного использования дисковой подсистемы и процессорного времени для поиска и сброса на диск неактивных страниц памяти.
Dirty - Измененные ("грязные") страницы, находящиеся в ОЗУ, но еще не сброшенные на диск. За процедуру записи на диск отвечает группа потоков ядра pdflush. В системе должно работать минимум два и максимум восемь потоков pdflush. Посмотреть текущее число потоков можно:
[root@server1 ~]# cat /proc/sys/vm/nr_pdflush_threads
2
Дополнительные потоки создаются в зависимости от текущей нагрузки ввода/вывода. Команда sync и "магическая" комбинация Alt-SysRq-S сбрасывает все "грязные" страницы и буферы. Число, хранящееся в vm.dirty_background_ratio (по умолчанию 10%), задает какой процент от ОЗУ потоки pdflush должны сбрасывать на диск. Чем больше процент, тем реже происходит обращение к диску. Второй из важных параметров, влияющих на pdflush, это процент от объема ОЗУ, при котором стартует сам процесс сброса на диск - vm.dirty_ratio.
Writeback - Страницы памяти, которые в настоящий момент сбрасываются на диск.
AnonPages - Анонимные страницы - это, как правило, данные, используемые программами и не ассоциированные с каким-либо файлом. Наряду со страницами, объем которых указан в Inactive, это первые кандидаты на попадание в область подкачки. Анонимные страницы нередко используются несколькими процессами. Самый распространенный пример - fork() при создании нового процесса. Число анонимных страниц для конкретного процесса можно вычислить как разницу между размером резидентной части (resident) и разделяемыми страницами (share) в выводе /proc/PID/statm (информация о состоянии памяти в страницах). Например:
[root@server1 vm]# cat /proc/$(pidof sshd)/statm
1763 258 161 93 0 130 0
Получается что число анонимных страниц для sshd = 258 - 161 = 97 или 388Кб. Подробнее - man proc.
Mapped - Общий объем памяти, привнесенный в виртуальное адресное пространство процессов при помощи mmap (например, библиотеки).
Slab - объем памяти, занятый под различные структуры ядра небольшого объема, для которых не оптимально выделять по целой странице памяти. По умолчанию в 32-р системах размер страницы - 4Кб, и этот объем является квантом памяти при ее выделении. Подробнее информацию о slab-кэше можно посмотреть при помощи утилиты vmstat с ключем -m, утилиты slabtop или через /proc/slabinfo.
PageTables - Объем памяти, зарезервированный под Таблицу Страниц.
NFS_Unstable - Данный параметр относится к клиенту NFS v3+, реализованному в ядре Linux, и показывает, какой объем данных, отправленных клиентом серверу, еще не был записан на диск. Клиент должен кэшировать эти данные до поступления подтверждения от сервера.
CommitLimit - Объем памяти, который может быть выделен системой. Вычисляется на основе vm.overcommit_ratio (по умолчанию - 50%) и размера области подкачки. Формула имеет следующий вид CommitLimit = ( vm.overcommit_ratio * объем_ОЗУ) + область_подкачки. Этот лимит соблюдается только при "строгой" политике выделения памяти (vm.overcommit_memory=2). По умолчанию используется "эвристическая" политика (vm.overcommit_memory=0).
Committed_AS - Сколько памяти выделено всем процессам, даже если они эту память не используют в полном объеме. Иными словами, данный параметр показывает, сколько при текущей загрузке системы требуется ОЗУ, если процессы реально захотят использовать выделенную память для того, чтобы избежать core dump по причине отсутствия памяти (OOM). Дело в том что, когда процесс требует - ядро подтверждает выделение требуемого объема памяти (только если не используется "строгая" политика. В этом случае проверяем, не исчерпан ли CommitLimit) без выделения ОЗУ. Реально память выделяется постранично только лишь когда процесс пытается что-то записать в выделенную до этого память. Этот механизм называется overcommitment. Более подробно см. /usr/share/doc/kernel-doc-*/Documentation/vm/overcommit-accounting.
VmallocTotal - общее число виртуального пространства, доступного для vmalloc.
VmallocUsed - объем использованного пространства vmalloc.
VmallocChunk - наибольший свободный непрерывный блок внутри пространства vmalloc.
Литература:
- Ядро Linux. 3-е издание, Даниель Бовет, Марко Чезати, БХВ-Петербург, 2007
- Optimizing Linux® Performance: A Hands-On Guide to Linux® Performance Tools, Phillip G. Ezolt, Pearson PTR, 2005
- Linux System Programming, Robert Love, O’Reilly, 2007
- /usr/share/doc/kernel-doc-*/Documentation/