мета-данные страницы
  •  

OOM killer

Любой запущенный процесс получает собственный выделенный участок памяти. Но этот участок не отображается на доступные физические адреса, а использует виртуальное адресное пространство, которое является дополнительным слоем абстракции между процессом и физической памятью. Для сопоставления адресов между виртуальной и физической памятью используются специальные структуры - таблицы страниц.

Что это дает? Во-первых, изоляцию процессов друг от друга, каждый из них работает в собственном виртуальном адресном пространстве и не имеет доступа к памяти других процессов. Во-вторых, позволяет системе гибко управлять физической памятью, например, для неактивного процесса часть страниц может быть перенесено из оперативной памяти в пространства подкачки, но это никак не повлияет на работу самого процесса, его адресное пространство не изменится, поменяется лишь трансляция в таблице страниц. И, наконец, это позволяет экономить физическую память, так если несколько процессов используют одни и те же данные, то система может транслировать адреса виртуальных пространств на один и тот же участок физической памяти.

Поэтому современные Linux-системы выделяют память процессам с превышением имеющейся в наличии физической памяти (RAM + Swap), по умолчанию используя эвристические механизмы. Но случается, что процессы съедают всю доступную физическую память и вот тут системе надо выбрать что-то одно. А выбор, скажем честно, между плохим или очень плохим. Можно убить один из процессов и продолжить работать дальше, а можно вызвать Kernel panic. Понятно, что последнее - это совсем ни в какие ворота, поэтому на сцену выходит OOM Killer, это поведение используется в современных Linux системах по умолчанию.

На самом деле OOM Killer использует достаточно сложный анализ и присваивает каждому процессу очки негодности (badness) и при исчерпании памяти будет убит не кто-попало, а самый негодный процесс. Очки негодности могут принимать значения от -1000 до 1000, чем выше значение, тем более высока вероятность что OOM Killer убьет процесс. Процесс с -1000 очков никогда не будет убит OOM Killer.

Как вычисляются очки негодности? За основу берется процент физической памяти используемый процессом и умножается на 10, таким образом получаем базовое значение. Нетрудно заметить, что 1000 очков - это 100% использования памяти. Затем к данному значению начинают применяться различные модификаторы:

  • Прибавляется половина очков всех дочерних процессов, имеющих собственную виртуальную память.
  • Если приоритет процесса больше нуля очки умножаются на два. Приоритет может иметь значение от -20 (наивысший приоритет) до 20 (самый низкий).
  • Очки делятся на коэффициент, связанный с процессорным временем, чем более активен процесс и чем больше процессорного времени он использует, тем больше будет этот коэффициент.
  • Очки делятся на коэффициент, связанный с временем жизни процесса, чем больше времени прошло с момента запуска, тем выше будет это значение.
  • Для процессов, запущенных от имени root, обслуживающих систему или процессов ввода-вывода очки делятся на 4.
  • Для процесса, при выделении памяти которому произошла ошибка out of memory и процессам имеющим с ним общую память, очки делятся на 8.
  • Очки умножаются на 2^oom_adj, где oom_adj - специальный коэффициент, имеющий значения от -17 до 15, при -17 процесс никогда не будет убить OOM Killer.

Если внимательно изучить эти критерии, то становится ясно, что OOM Killer убьет самый «толстый» процесс, который наименее активен в системе и имеет самое короткое время жизни

Количество очков находится в /proc/PID/oom_score. Соответсвтенно, присвоить значение вручную можно так: echo -17 > /proc/PID/oom_adj. Заранее определить коэффицент oom_adj для еще не запущенного процесса можно через систему инициализации.