Estaba ejecutando un script de shell con comandos para ejecutar varios programas intensivos en memoria (2-5 GB) de forma consecutiva. Cuando volví a verificar el progreso de mi script, me sorprendió descubrir que algunos de mis procesos eran Killed
, como me informó mi terminal. Varios programas ya se habían completado sucesivamente antes de los programas que se Killed
iniciaron más tarde , pero todos los programas luego fallaron en una falla de segmentación (que puede o no haber sido debido a un error en mi código, sigue leyendo).
Miré el historial de uso del clúster en particular que estaba usando y vi que alguien comenzó a ejecutar varios procesos intensivos en memoria al mismo tiempo y al hacerlo agotó la memoria real (y posiblemente incluso el espacio de intercambio) disponible para el clúster. Lo mejor que puedo imaginar, estos procesos intensivos en memoria comenzaron a ejecutarse casi al mismo tiempo que comencé a tener problemas con mis programas.
¿Es posible que Linux haya matado mis programas una vez que comenzó a quedarse sin memoria? ¿Y es posible que las fallas de segmentación que obtuve más tarde se debieran a la falta de memoria disponible para ejecutar mis programas (en lugar de un error en mi código)?
fuente
Respuestas:
Puede.
Hay dos condiciones diferentes de falta de memoria que puede encontrar en Linux. Lo que encuentre depende del valor de
sysctl vm.overcommit_memory
(/proc/sys/vm/overcommit_memory
)Introducción:
el núcleo puede realizar lo que se denomina "sobrecompromiso de memoria". Esto es cuando el núcleo asigna a los programas más memoria de la que realmente está presente en el sistema. Esto se hace con la esperanza de que los programas no usen toda la memoria que asignaron, ya que esto es algo bastante común.
overcommit_memory = 2
Cuando
overcommit_memory
se establece en2
, el kernel no realiza ningún compromiso excesivo en absoluto. En cambio, cuando se asigna memoria a un programa, se garantiza el acceso para tener esa memoria. Si el sistema no tiene suficiente memoria libre para satisfacer una solicitud de asignación, el kernel simplemente devolverá un error para la solicitud. Depende del programa manejar con gracia la situación. Si no comprueba que la asignación se realizó correctamente cuando realmente falló, la aplicación a menudo encontrará una falla de seguridad.En el caso de la segfault, debe encontrar una línea como esta en la salida de
dmesg
:Esto
at 0
significa que la aplicación intentó acceder a un puntero no inicializado, que puede ser el resultado de una llamada de asignación de memoria fallida (pero no es la única forma).overcommit_memory = 0 y 1
Cuando
overcommit_memory
se establece en0
o1
, se habilita el sobrecompromiso, y los programas pueden asignar más memoria de la que realmente está disponible.Sin embargo, cuando un programa quiere usar la memoria que le fue asignada, pero el núcleo descubre que en realidad no tiene suficiente memoria para satisfacerlo, necesita recuperar algo de memoria. Primero intenta realizar varias tareas de limpieza de memoria, como vaciar cachés, pero si esto no es suficiente, terminará un proceso. Esta terminación es realizada por el OOM-Killer. El OOM-Killer observa el sistema para ver qué programas están usando qué memoria, cuánto tiempo han estado ejecutándose, quién los está ejecutando y una serie de otros factores para determinar cuál es el que se mata.
Después de que el proceso ha finalizado, la memoria que estaba usando se libera y el programa que acaba de causar la falta de memoria ahora tiene la memoria que necesita.
Sin embargo, incluso en este modo, a los programas todavía se les pueden denegar las solicitudes de asignación. Cuando
overcommit_memory
es así0
, el kernel intenta adivinar cuándo debería comenzar a denegar las solicitudes de asignación. Cuando se establece en1
, no estoy seguro de qué determinación utiliza para determinar cuándo debe rechazar una solicitud, pero puede rechazar solicitudes muy grandes.Puede ver si el OOM-Killer está involucrado mirando la salida de
dmesg
y encontrando mensajes como:fuente
overcommit_memory
se establece en 0 o 2.overcommit_memory=2
el asesino OOM ni siquiera está habilitado, entonces controlarlo es irrelevante. Sin embargo, una vez que establecemos que es el asesino de OOM, se convierte en otro tema que está cubierto por muchas otras preguntas y respuestas aquí.La verdad es que, independientemente de la forma en que lo mire, ya sea que su proceso se atascó debido al administrador de memoria del sistema o debido a algo más, sigue siendo un error. ¿Qué pasó con todos esos datos que acababas de procesar en la memoria? Debería haber sido guardado.
Si bien
overcommit_memory=
es la forma más general de configurar la administración OOM de Linux, también es ajustable por proceso como:El uso
-17
en lo anterior excluirá un proceso de la administración de falta de memoria. Probablemente no sea una gran idea en general, pero si está buscando errores, puede valer la pena, especialmente si desea saber si fue OOM o su código. Incrementar positivamente el número hará que el proceso sea más probable que se elimine en un evento OOM, lo que podría permitirle apuntalar mejor la capacidad de recuperación de su código en situaciones de poca memoria y garantizar que salga con gracia cuando sea necesario.Puede verificar la configuración actual del controlador OOM por proceso como:
De lo contrario, podría suicidarse:
Eso configurará la computadora para reiniciar en caso de una condición de falta de memoria. Establece lo
X
anterior en la cantidad de segundos que desea que la computadora se detenga después de un pánico del kernel antes de reiniciar. Enloquecer.Y si, por alguna razón, decides que te gusta, hazlo persistente:
fuente