Я запускал сценарий оболочки с командами для запуска нескольких ресурсоемких программ (2-5 ГБ) подряд. Когда я вернулся, чтобы проверить ход выполнения моего сценария, я с удивлением обнаружил, что некоторые из моих процессов были Killed
такими, как сообщил мне мой терминал. Несколько программ уже были успешно завершены до Killed
запуска программ, которые позже были запущены, но впоследствии все программы потерпели неудачу из-за ошибки сегментации (которая могла или не могла быть вызвана ошибкой в моем коде, продолжайте читать).
Я посмотрел историю использования конкретного кластера, который использовал, и увидел, что кто-то начал запускать несколько процессов, интенсивно использующих память, и при этом исчерпал реальную память (и, возможно, даже пространство подкачки), доступную для кластера. Насколько я могу судить, эти процессы, интенсивно использующие память, начали выполняться примерно в то же время, когда у меня возникли проблемы с моими программами.
Возможно ли, что Linux убил мои программы после того, как началось нехватка памяти? И возможно ли, что ошибки сегментации, которые я получил позже, были вызваны нехваткой памяти, доступной для запуска моих программ (вместо ошибки в моем коде)?
источник
Ответы:
Может.
Есть два разных состояния нехватки памяти, с которыми вы можете столкнуться в Linux. То, с чем вы столкнетесь, зависит от значения
sysctl vm.overcommit_memory
(/proc/sys/vm/overcommit_memory
)Введение:
ядро может выполнять то, что называется «переполнение памяти». Это когда ядро выделяет программам больше памяти, чем на самом деле присутствует в системе. Это делается в надежде на то, что программы на самом деле не будут использовать всю выделенную ими память, поскольку это довольно распространенное явление.
overcommit_memory = 2
Когда
overcommit_memory
установлено значение2
, ядро не выполняет никакого overcommit вообще. Вместо этого, когда программе выделяется память, ей гарантирован доступ к этой памяти. Если в системе недостаточно свободной памяти для удовлетворения запроса на выделение, ядро просто вернет ошибку для запроса. Программа должна изящно справиться с ситуацией. Если он не проверяет, что выделение прошло успешно, когда оно действительно не удалось, приложение часто будет сталкиваться с segfault.В случае с segfault вы должны найти такую строку в выводе
dmesg
:В
at 0
означает , что приложение пытались получить доступ неинициализированный указатель, который может быть результатом неудачного вызова выделения памяти (но это не единственный способ).overcommit_memory = 0 и 1
Когда
overcommit_memory
установлено значение0
или1
, избыточная передача включена, и программам разрешается выделять больше памяти, чем реально доступно.Однако, когда программа хочет использовать память, которая была ей выделена, но ядро обнаруживает, что на самом деле у нее недостаточно памяти для ее удовлетворения, ей необходимо вернуть часть памяти. Сначала он пытается выполнить различные задачи очистки памяти, такие как очистка кэшей, но если этого недостаточно, он завершит процесс. Это прекращение выполняется OOM-Killer. OOM-Killer просматривает систему, чтобы увидеть, какие программы используют какую память, как долго они работают, кто их запускает и ряд других факторов, чтобы определить, какой из них будет убит.
После завершения процесса память, которую он использовал, освобождается, и программа, которая только что вызвала состояние нехватки памяти, теперь имеет память, в которой она нуждается.
Однако даже в этом режиме программам все равно может быть отказано в распределении запросов. Когда
overcommit_memory
это так0
, ядро пытается определить, когда оно должно начать отклонять запросы на выделение. Когда он установлен на1
, я не уверен, какое определение он использует, чтобы определить, когда ему следует отклонить запрос, но он может отклонить очень большие запросы.Вы можете увидеть, участвует ли OOM-Killer, посмотрев выходные данные
dmesg
и найдя такие сообщения, как:источник
overcommit_memory
установлено значение 0 или 2.overcommit_memory=2
убийца OOM даже не включен, то контролировать его не имеет значения. Однако, как только мы установим, что это убийца OOM, это становится другой темой, в которой рассматриваются многие другие вопросы и ответы здесь.Правда в том, что независимо от того, как вы на это смотрите - будь то ваш процесс захлебнулся из-за системного менеджера памяти или из-за чего-то другого - это все равно ошибка. Что случилось со всеми этими данными, которые вы просто обрабатывали в памяти? Это должно было быть сохранено.
Хотя
overcommit_memory=
это наиболее общий способ настройки управления OOM в Linux, он также настраивается для каждого процесса, например:Использование
-17
в вышеупомянутом исключит процесс из управления нехваткой памяти. Возможно, это не очень хорошая идея, но если вы ищете ошибки, это может быть полезно, особенно если вы хотите знать, был ли это OOM или ваш код. Положительное увеличение числа увеличит вероятность того, что процесс будет прерван в событии OOM, что может помочь вам повысить устойчивость вашего кода в ситуациях с нехваткой памяти и обеспечить корректный выход при необходимости.Вы можете проверить текущие настройки обработчика OOM для каждого процесса, например:
В противном случае вы можете пойти на самоубийство:
Это приведет к перезагрузке компьютера в случае нехватки памяти. Вы указываете
X
количество секунд, в течение которых компьютер должен останавливаться после паники ядра перед перезагрузкой. Неистовствовать.И если по какой-то причине вы решили, что вам это нравится, сделайте это настойчивым:
источник