GNU/Linux >> Tutoriales Linux >  >> Linux

Situación de oom de Linux (kernel de 32 bits)

Solución 1:

Sin embargo, un enfoque de 'mazo' sería actualizar a un sistema operativo de 64 bits (esto es de 32 bits) porque el diseño de las zonas se hace de manera diferente.

Bien, aquí intentaré responder por qué ha experimentado un OOM aquí. Hay una serie de factores en juego aquí.

  • El tamaño del pedido de la solicitud y cómo el kernel trata ciertos tamaños de pedido.
  • La zona que se está seleccionando.
  • Las marcas de agua que utiliza esta zona.
  • Fragmentación en la zona.

Si observa el propio OOM, claramente hay mucha memoria libre disponible, pero ¿se invocó OOM-killer? ¿Por qué?

El tamaño del pedido de la solicitud y cómo el núcleo trata ciertos tamaños de pedido

El núcleo asigna memoria por orden. Una 'orden' es una región de RAM contigua que debe cumplirse para que la solicitud funcione. Los pedidos se organizan por órdenes de magnitud (por lo tanto, el orden del nombre) utilizando el algoritmo 2^(ORDER + 12) . Entonces, el pedido 0 es 4096, el pedido 1 es 8192, el pedido 2 es 16384 y así sucesivamente.

El kernel tiene un valor codificado de lo que se considera un 'orden alto' (> PAGE_ALLOC_COSTLY_ORDER ). Este es el pedido 4 y superior (64 kb o superior es un pedido alto).

Los pedidos altos se satisfacen para las asignaciones de páginas de manera diferente a los pedidos bajos. Una asignación de alto orden si no logra capturar la memoria, en los núcleos modernos lo hará.

  • Intente ejecutar en la memoria la rutina de compactación para desfragmentar la memoria.
  • Nunca llame a OOM-killer para satisfacer la solicitud.

El tamaño de su pedido aparece aquí

Dec 27 09:19:05 2013 kernel: : [277622.359064] squid invoked oom-killer: gfp_mask=0x42d0, order=3, oom_score_adj=0

La Orden 3 es la más alta de las solicitudes de orden bajo y (como puede ver) invoca el OOM-killer en un intento de satisfacerlo.

Tenga en cuenta que la mayoría de las asignaciones de espacio de usuario no utilizan solicitudes de orden superior. Por lo general, es el kernel el que requiere regiones contiguas de memoria. Una excepción a esto puede ser cuando el espacio de usuario usa páginas enormes, pero ese no es el caso aquí.

En su caso, el kernel llama a la asignación de orden 3 que desea poner en cola un paquete en la pila de la red, lo que requiere una asignación de 32 kb para hacerlo.

La zona que se está seleccionando.

El núcleo divide sus regiones de memoria en zonas. Este corte se realiza porque en x86 ciertas regiones de la memoria solo son direccionables por cierto hardware. Es posible que el hardware más antiguo solo pueda direccionar la memoria en la zona 'DMA', por ejemplo. Cuando queremos asignar algo de memoria, primero se elige una zona y solo la memoria libre de esta zona se tiene en cuenta al tomar una decisión de asignación.

Si bien no estoy completamente informado sobre el algoritmo de selección de zona, el caso de uso típico nunca es asignar desde DMA, sino seleccionar la zona direccionable más baja que podría satisfacer la solicitud.

Se escupe mucha información de zona durante OOM que también se puede obtener de /proc/zoneinfo .

Dec 27 09:19:05 2013 kernel: : [277622.359382] DMA free:2332kB min:36kB low:44kB high:52kB active_anon:0kB inactive_anon:0kB active_file:0kB inactive_file:0kB unevictable:0kB isolated(anon):0kB isolated(file):0kB present:15968kB managed:6960kB mlocked:0kB dirty:0kB writeback:0kB mapped:0kB shmem:0kB slab_reclaimable:8kB slab_unreclaimable:288kB kernel_stack:0kB pagetables:0kB unstable:0kB bounce:0kB free_cma:0kB writeback_tmp:0kB pages_scanned:0 all_unreclaimable? yes
Dec 27 09:19:05 2013 kernel: : [277622.359393] Normal free:114488kB min:3044kB low:3804kB high:4564kB active_anon:0kB inactive_anon:0kB active_file:252kB inactive_file:256kB unevictable:0kB isolated(anon):0kB isolated(file):0kB present:894968kB managed:587540kB mlocked:0kB dirty:0kB writeback:0kB mapped:4kB shmem:0kB slab_reclaimable:117712kB slab_unreclaimable:138616kB kernel_stack:11976kB pagetables:0kB unstable:0kB bounce:0kB free_cma:0kB writeback_tmp:0kB pages_scanned:982 all_unreclaimable? yes
Dec 27 09:19:05 2013 kernel: : [277622.359404] HighMem free:27530668kB min:512kB low:48272kB high:96036kB active_anon:2634060kB inactive_anon:217596kB active_file:4688452kB inactive_file:1294168kB unevictable:0kB isolated(anon):0kB isolated(file):0kB present:36828872kB managed:36828872kB mlocked:0kB dirty:0kB writeback:0kB mapped:183132kB shmem:39400kB slab_reclaimable:0kB slab_unreclaimable:0kB kernel_stack:0kB pagetables:430856kB unstable:0kB bounce:367564104kB free_cma:0kB writeback_tmp:0kB pages_scanned:0 all_unreclaimable? no

Las zonas que tiene, DMA, Normal y HighMem indican una plataforma de 32 bits, porque la zona HighMem no existe en 64 bits. También en los sistemas de 64 bits, Normal se asigna a 4 GB y más, mientras que en 32 bits se asigna hasta 896 Mb (aunque, en su caso, el kernel informa que solo administra una porción más pequeña que esta:- managed:587540kB .)

Es posible saber de dónde provino esta asignación mirando de nuevo la primera línea, gfp_mask=0x42d0 nos dice qué tipo de asignación se hizo. El último byte (0) nos dice que se trata de una asignación de la zona normal. Los significados de gfp se encuentran en include/linux/gfp.h.

Las marcas de agua que utiliza esta zona.

Cuando la memoria es baja, las acciones para recuperarla se especifican mediante la marca de agua. Aparecen aquí:min:3044kB low:3804kB high:4564kB . Si la memoria libre llega a 'bajo', se producirá un intercambio hasta que superemos el umbral 'alto'. Si la memoria llega a 'min', necesitamos matar cosas para liberar memoria a través del OOM-killer.

Fragmentación en la zona.

Para ver si se puede satisfacer una solicitud de un pedido específico de memoria, el kernel contabiliza cuántas páginas libres y disponibles de cada pedido. Esto es legible en /proc/buddyinfo . Los informes OOM-killer también escupen la información de amigos como se ve aquí:

Normal: 5360*4kB (UEM) 3667*8kB (UEM) 3964*16kB (UEMR) 13*32kB (MR) 0*64kB 1*128kB (R) 1*256kB (R) 0*512kB 0*1024kB 0*2048kB 0*4096kB = 115000kB

Para que se satisfaga una asignación de memoria, debe haber memoria libre disponible en el tamaño del pedido solicitado o una asignación superior. Tener montones y montones de datos gratuitos en los órdenes bajos y ninguno en los órdenes altos significa que su memoria está fragmentada. Si obtiene una asignación de orden muy alta, es posible (incluso con mucha memoria libre) que no se satisfaga debido a que no hay páginas de orden alto disponibles. El kernel puede desfragmentar la memoria (esto se denomina compactación de la memoria) moviendo muchas páginas de bajo orden para que no dejen espacios en el espacio RAM direccionable.

¿Se invocó el asesino de OOM? ¿Por qué?

Entonces, si tenemos en cuenta estas cosas, podemos decir lo siguiente:

  • Se intentó una asignación contigua de 32kB. De la zona normal.
  • Había suficiente memoria libre en la zona seleccionada.
  • Había orden 3, 5 y 6 de memoria disponible 13*32kB (MR) 1*128kB (R) 1*256kB (R)

Entonces, si hubiera hubo memoria libre, otras órdenes podrían satisfacer la solicitud. ¿Qué pasó?

Bueno, hay más en la asignación de un pedido que solo verificar la cantidad de memoria libre disponible para ese pedido o superior. El núcleo sustrae efectivamente la memoria de todos los órdenes inferiores de la línea libre total y luego realiza la verificación de la marca de agua mínima en lo que queda.

Lo que pasa en tu caso es revisar nuestra memoria libre para esa zona debemos hacer.

115000 - (5360*4) - (3667*8) - (3964*16) = 800

Esta cantidad de memoria libre se compara con el min marca de agua, que es 3044. Por lo tanto, técnicamente hablando, no le queda memoria libre para hacer la asignación que solicitó. Y es por eso que invocaste OOM-killer.

Reparación

Hay dos arreglos. La actualización a 64 bits cambia el particionamiento de su zona, de modo que 'Normal' es de 4 GB a 36 GB, por lo que no terminará 'predeterminando' su asignación de memoria en una zona que puede estar tan fragmentada. No es que tenga más memoria direccionable lo que soluciona este problema (porque ya está usando PAE), simplemente que la zona que seleccione tiene más memoria direccionable.

La segunda forma (que nunca he probado) es intentar que el kernel compacte más agresivamente su memoria.

Si cambia el valor de vm.extfrag_threshold de 500 a 100, es más probable que se compacte la memoria en un intento de cumplir con una asignación de orden superior. Aunque, nunca antes me había metido con este valor; también dependerá de cuál sea su índice de fragmentación, que está disponible en /sys/kernel/debug/extfrag/extfrag_index . No tengo una caja en este momento con un núcleo lo suficientemente nuevo como para ver qué ofrece más que esto.

Alternativamente, podría ejecutar algún tipo de trabajo cron (esto es horrible, horriblemente feo) para compactar manualmente la memoria escribiendo en /proc/sys/vm/compact_memory .

Sin embargo, sinceramente, no creo que haya una manera de ajustar el sistema para evitar este problema:es la naturaleza del asignador de memoria el que funcione de esta manera. Cambiar la arquitectura de la plataforma que utiliza es probablemente la única solución fundamentalmente resoluble.

Solución 2:

Desde el principio:deberías realmente Ir a un sistema operativo de 64 bits. ¿Tiene una buena razón para quedarse en 32 bits aquí?

Es difícil diagnosticar este problema sin observar el sistema más de cerca, preferiblemente en el momento en que falla, por lo que mi publicación (rápida) está dirigida más o menos genéricamente a problemas de memoria en sistemas de 32 bits. ¿Mencioné que pasar a 64 bits haría que todo esto desapareciera?

Tu problema es triple.

En primer lugar, incluso en un kernel PAE, el espacio de direcciones por proceso está limitado a 4GiB[1]. Esto significa que su instancia de squid nunca podrá consumir más de 4 GiB de RAM por proceso. No estoy tan familiarizado con squid, pero si este es su servidor proxy principal, puede que no sea suficiente de todos modos.

En segundo lugar, en un sistema de 32 bits con grandes cantidades de RAM, se usa mucha memoria en lo que se llama 'ZONE_NORMAL' para almacenar estructuras de datos que se necesitan para usar la memoria en ZONE_HIGHMEM. Estas estructuras de datos no se pueden mover a ZONE_HIGHMEM, porque la memoria que usa el kernel para sus propios fines siempre debe estar en ZONE_NORMAL (es decir, en los primeros 1GiB). Cuanta más memoria tenga en ZONE_HIGHMEM (mucha, en su caso), más se convierte esto en un problema, porque el kernel necesita más y más memoria de ZONE_NORMAL para administrar ZONE_HIGHMEM. A medida que se agota la cantidad de memoria libre en ZONE_NORMAL, su sistema puede fallar en algunas tareas, porque ZONE_NORMAL es donde mucho de cosas suceden en un sistema de 32 bits. Todas las operaciones de memoria relacionadas con el kernel, por ejemplo;)

En tercer lugar, incluso si queda algo de memoria en ZONE_NORMAL (no he revisado sus registros en detalle), algunas operaciones de memoria requerirán memoria no fragmentada. Por ejemplo, si toda su memoria está fragmentada en partes realmente pequeñas, algunas operaciones que necesitan más que eso fallarán. [3] Una breve mirada a sus registros muestra una cantidad bastante significativa de fragmentación en ZONE_DMA y ZONE_NORMAL.

Editar:la respuesta anterior de Mlfe tiene una excelente explicación de cómo funciona esto en detalle.

Nuevamente:en un sistema de 64 bits, toda la memoria está en ZONE_NORMAL. No hay zona HIGHMEM en sistemas de 64 bits. Problema resuelto.

Editar:podría echar un vistazo aquí [4] para ver si puede decirle a oom-killer que deje en paz sus procesos importantes. Eso no resolverá todo (si es que soluciona algo), pero podría valer la pena intentarlo.

[1] http://en.wikipedia.org/wiki/Physical_address_extension#Design

[2] http://www.redhat.com/archives/rhelv5-list/2008-September/msg00237.html y https://access.redhat.com/site/documentation/en-US/Red_Hat_Enterprise_Linux/5/html /Tuning_and_Optimizing_Red_Hat_Enterprise_Linux_for_Oracle_9i_and_10g_Databases/sect-Oracle_9i_and_10g_Tuning_Guide-Hardware_Architectures_and_Linux_Kernels-a32_bit_Architecture_and_the_hugemem_Kernel.html

[3] http://bl0rg.krunch.be/oom-frag.html

[4] http://lwn.net/Articles/317814/

Solución 3:

@MIfe ya proporcionó una excelente redacción sobre cómo se manejan las asignaciones de memoria en el kernel y también le proporcionó una solución adecuada, como cambiar a un sistema operativo de 64 bits y un truco desagradable como la compactación manual de memoria a través de /proc/sys/vm/compact_memory en cron .

Mis 2 centavos serían otra solución que puede ayudarlo:
He notado que tienes tcp_tso_segment en su kernel backtrace, haciendo lo siguiente:

# ethtool -K ethX tso off gso off lro off

puede disminuir la presión en mm obligándolo a usar órdenes inferiores.

PD . la lista de todas las descargas se puede obtener a través de # ethtool -k ethX

Solución 4:

El pánico se debe a que el sysctl "vm.panic_on_oom =1" está configurado; la idea es que reiniciar el sistema lo devuelve a un estado cuerdo. Puede cambiar esto en sysctl.conf.

Justo en la parte superior leemos squid invocado oom killer. Puede verificar su configuración de squid y su uso máximo de memoria (o simplemente pasar a un sistema operativo de 64 bits).

/proc/meminfo muestra una zona de memoria alta en uso, por lo que está ejecutando un kernel de 32 bits con 36 GB de memoria. También puede ver que en la zona normal, para satisfacer la demanda de memoria de squid, el kernel escaneó 982 páginas sin éxito:

pages_scanned:982 all_unreclaimable? yes

Linux
  1. Linux:¿un núcleo corrupto en Linux?

  2. ¿Núcleo de Linux para Nintendo Wii?

  3. Linux:¿los diferentes kernels de Linux/unix son intercambiables?

  4. ¿Cómo determina el kernel de Linux el orden de las llamadas __init?

  5. ¿Cómo sé si mi kernel de Linux se ejecuta en 32 o 64 bits?

¿Linux es un sistema operativo o un kernel?

Núcleo de Linux vs. Núcleo de Mac

Kernel de Linux y sus funciones

Qué hacer en caso de pánico en el kernel de Linux

Guía completa de registro de Linux

Linux – Diagrama de Linux Kernel vs. Herramientas de rendimiento?