Назад | Перейти на главную страницу

Как вообще может быть сценарий OOM в Linux (эвристика убийцы OOM)?

Я знаю концепцию виртуальной памяти. А с подкачкой по запросу (в зависимости от vm.overcommit_memory) вы можете выделить больше памяти, чем доступная RAM. Пока вы не «прикоснетесь» к странице, ничего не произойдет. В противном случае, я предполагаю, что есть ошибка страницы, и для страничного фрейма используется физическая память. Но это каким-то образом означает, что, если системе не хватает памяти, она просто выгружает последние недавно использованные данные и работает нормально.

Как вообще может возникнуть необходимость убить процесс? Это происходит из-за того, что mlock () слишком много памяти - ред. OOM вызывается после того, как слишком много мусора? Или спросить по-другому: какова именно эвристика срабатывания убийцы OOM?

Я читал, что вы можете сделать "echo 1> memory.oom_control" или "echo -17> / proc / PID / oom_adj", чтобы отключить его. Каковы последствия этого? Машина, вероятно, какое-то время полностью перестанет отвечать на запросы. Но если каким-то образом нарушающий процесс обнаруживает, что он не прогрессирует, он также может временно прекратить потребление памяти (так быстро), и в конечном итоге все должно снова начать работать, или я ошибаюсь?

В моем сценарии есть только один процесс (с огромным кешем в памяти). Эти данные, конечно, не являются постоянными, но я бы предпочел не перезапускать процесс (и перезагружать эти данные).

Кажется, вы не понимаете, как связаны виртуальная память и чрезмерное использование.

Физическая память состоит из микросхем оперативной памяти вашего компьютера. Физически невозможно когда-либо использовать больше памяти одновременно, чем у вас есть физическая память. Однако с конца 1970-х годов появилась виртуальная память, в которой система перемещает некоторые данные из физической памяти на диск, тем самым сохраняя память, которая фактически не используется, поэтому физическую память можно использовать для других целей. Когда это происходит, программы не могут сразу использовать данные, которые были выгружены; когда они все равно попытаются это сделать, процессор сгенерирует ошибка страницы, заставляя операционную систему загружать необходимые данные из свопа обратно в физическую память.

При использовании виртуальной памяти общий объем данных в полете, которые могут использоваться, увеличивается до размера физической памяти плюс пространство подкачки. Хотя это позволяет системе запускать больше программ одновременно, объем памяти фактически используется никогда не может превышать общую доступную виртуальный память (т.е. RAM + пространство подкачки)

В принципе, ядро ​​должно отслеживать объем памяти, который программы запросили у него, и должно отклонять запросы на дополнительную память, как только его бухгалтерия сообщает ему, что вся память была занята. выделенный, хотя не все это могло быть используемый. Большинство других ядер делают это, поэтому у них нет убийцы OOM (потому что он им не нужен).

Однако системный вызов программы для выделения памяти из ядра не выделяет память по байтам; он распределяет его по более крупным блокам. Напротив, реальная реализация, используемая большинством программ для получения памяти ( malloc() Функция библиотеки C) делает позволяют программам выделять память по байтам. Это означает, что большинство программ, когда они запрашивают некоторую память, заканчивают malloc() выделяют больше, чем им действительно нужно. Кроме того, хороший malloc() реализация будет использовать некоторую эвристику, чтобы разделять меньшие и большие выделения, так что фрагментация памяти не такая уж плохая, но для этого требуется, чтобы она запрашивала больше памяти у ядра, что усугубляет проблему. В результате этих и других эффектов, без чрезмерного выделения памяти, будут выделены большие объемы памяти, но они будут никогда использоваться.

Идея чрезмерных обязательств заключается в том, что вы можете безопасно выделить некоторые больше памяти, чем общий объем виртуальной памяти, доступной вашей системе, без обратной связи. По сути, ядро ​​утверждает, что разрешает выделение, даже если оно знает он не может выполнить это обещание в предположении, что ему не нужно будет выполнять эти обещания в полной мере. Однако невозможно предсказать точную сумму, которая может быть превышена - выделена - без каких-либо сбоев; поэтому, когда ядро ​​обнаруживает, что программы пытаются использовать всю выделенную им память, ядру придется отказаться от своих обещаний. Вот здесь и появляется убийца OOM.

Вопрос о том, хорошая ли это идея, остается предметом обсуждения. Когда в системе заканчивается память, что-то пойдет не так. Если это случай, когда какое-то приложение пытается выделить больше памяти, но ядро ​​уже зарезервировало все, тогда, возможно, это конкретное приложение выйдет из строя. Если это просто ваш X-сервер, вам не повезло. По крайней мере, если есть убийца OOM, он может решить, какой процесс убить, а не что-то пойдет не так после плохого распределения; и у OOM killer есть некоторая логика, чтобы не убивать важные процессы, такие как ваш X-сервер ...

Однако, если вы предпочитаете, есть несколько регуляторов sysctl, которые вы можете использовать, чтобы отключить избыточную фиксацию, если вы думаете, что это плохая идея.