¿Puede Linux "quedarse sin RAM"?

20

Vi varias publicaciones en la web de personas que aparentemente se quejaban de un VPS alojado que mataba procesos inesperadamente porque usaban demasiada RAM.

¿Cómo es esto posible? Pensé que todos los sistemas operativos modernos proporcionan "RAM infinita" simplemente usando el intercambio de disco para todo lo que pasa por la RAM física. ¿Es esto correcto?

¿Qué podría estar sucediendo si un proceso se "cancela debido a poca RAM"?

el espejo
fuente
12
Ningún sistema operativo tiene RAM infinita . Además de los chips físicos de RAM en la máquina, los sistemas operativos pueden, por lo general, opcionalmente, usar el llamado 'archivo de intercambio' que está en el disco. Cuando una computadora necesita más memoria de la que tiene en las memorias RAM, intercambia algunas cosas en el archivo de intercambio. Pero a medida que el archivo de intercambio alcanza su capacidad, ya sea porque establece un tamaño máximo (típico) o el disco se llena, se queda sin memoria virtual.
John Dibling
@JohnDibling; Entonces, ¿hay alguna razón por la que uno quiera limitar el tamaño de intercambio además de ahorrar espacio en disco para el sistema de archivos? En otras palabras, si tengo un disco de 20 GB y solo 1 GB de archivos, ¿hay alguna razón para no establecer mi tamaño de intercambio en 19 GB?
themirror
1
Para simplificar demasiado las cosas, diría que las dos razones para limitar el tamaño de intercambio son 1) para reducir el consumo de disco y 2) para aumentar el rendimiento. Esto último podría ser más cierto en Windows que / * NIX, pero, de nuevo, si está utilizando el espacio de intercambio en su disco, su rendimiento se degrada. El acceso al disco es más lento que la RAM o mucho más lento que la RAM, dependiendo del sistema.
John Dibling
99
El intercambio no es RAM . en.wikipedia.org/wiki/Random-access_memory La cantidad de RAM en su sistema es la cantidad de RAM en su sistema - punto. No es un volumen ambiguo o dinámico. Está absolutamente arreglado. "Memoria" es un concepto más ambiguo, pero la distinción entre RAM y otras formas de almacenamiento es, como señala terdon (+1), bastante significativa. El intercambio de disco no puede sustituir el rendimiento de la RAM en muchos órdenes de magnitud . Un sistema que depende excesivamente del intercambio es, en el mejor de los casos, temporal y, en general, basura.
Ricitos de oro
1
¿Entonces el espacio en disco es infinito ahora?
Kaz

Respuestas:

41

¿Qué podría estar sucediendo si un proceso se "cancela debido a poca RAM"?

A veces se dice que Linux por defecto nunca niega las solicitudes de más memoria del código de la aplicación, por ejemplo malloc().1 Esto no es de hecho cierto; el valor predeterminado utiliza un heurístico por el cual

Los excesos obvios de espacio de direcciones se rechazan. Usado para un sistema típico. Asegura que una asignación seriamente grave falle mientras permite un exceso de compromiso para reducir el uso de intercambio.

De [linux_src]/Documentation/vm/overcommit-accounting(todas las citas son del árbol 3.11). Exactamente lo que cuenta como una "asignación seriamente salvaje" no se hace explícito, por lo que tendríamos que pasar por la fuente para determinar los detalles. También podríamos usar el método experimental en la nota al pie 2 (a continuación) para tratar de obtener un reflejo de la heurística; en base a eso, mi observación empírica inicial es que, en circunstancias ideales (== el sistema está inactivo), si no lo hace ' No tiene ningún intercambio, se le permitirá asignar aproximadamente la mitad de su RAM, y si lo hace, obtendrá aproximadamente la mitad de su RAM más todo su intercambio. Eso es más o menos por proceso (pero tenga en cuenta que este límite es dinámico y está sujeto a cambios debido al estado, ver algunas observaciones en la nota 5).

La mitad de su intercambio RAM plus es explícitamente el valor predeterminado para el campo "CommitLimit" en /proc/meminfo. Esto es lo que significa, y tenga en cuenta que en realidad no tiene nada que ver con el límite que se acaba de discutir (de [src]/Documentation/filesystems/proc.txt):

CommitLimit: basado en la relación de sobrecompromiso ('vm.overcommit_ratio'), esta es la cantidad total de memoria disponible actualmente para ser asignada en el sistema. Este límite solo se cumple si se habilita la contabilidad estricta de sobrecompromiso (modo 2 en 'vm.overcommit_memory'). El CommitLimit se calcula con la siguiente fórmula: CommitLimit = ('vm.overcommit_ratio' * RAM física) + Swap Por ejemplo, en un sistema con 1G de RAM física y 7G de swap con un 'vm.overcommit_ratio' de 30 produciría un CommitLimit de 7.3G.

El documento de contabilidad de sobrecompromiso citado anteriormente establece que el valor predeterminado vm.overcommit_ratioes 50. Entonces, si puede sysctl vm.overcommit_memory=2, puede ajustar vm.covercommit_ratio (con sysctl) y ver las consecuencias. 3 El modo predeterminado, cuando CommitLimitno se aplica y solo "se rechazan las sobrecompresiones obvias de espacio de direcciones", es cuándo vm.overcommit_memory=0.

Si bien la estrategia predeterminada tiene un límite heurístico por proceso que impide la "asignación seriamente salvaje", sí deja al sistema en su conjunto libre para ponerse seriamente salvaje, en cuanto a la asignación. 4 Esto significa que en algún momento puede quedarse sin memoria y tener que declararse en bancarrota en algunos procesos a través del asesino OOM .

¿Qué mata el asesino OOM? No es necesariamente el proceso que pedía memoria cuando no había ninguno, ya que ese no es necesariamente el proceso verdaderamente culpable y, lo que es más importante, no necesariamente el que sacará al sistema más rápidamente del problema en el que se encuentra.

Aquí se cita esto, que probablemente cita una fuente 2.6.x:

/*
 * oom_badness - calculate a numeric value for how bad this task has been
 *
 * The formula used is relatively simple and documented inline in the
 * function. The main rationale is that we want to select a good task
 * to kill when we run out of memory.
 *
 * Good in this context means that:
 * 1) we lose the minimum amount of work done
 * 2) we recover a large amount of memory
 * 3) we don't kill anything innocent of eating tons of memory
 * 4) we want to kill the minimum amount of processes (one)
 * 5) we try to kill the process the user expects us to kill, this
 *    algorithm has been meticulously tuned to meet the principle
 *    of least surprise ... (be careful when you change it)
 */

Lo que parece una justificación decente. Sin embargo, sin ser forense, el n. ° 5 (que es redundante del n. ° 1) parece una implementación de venta difícil, y el n. ° 3 es redundante del n. ° 2. Por lo tanto, podría tener sentido considerar esto reducido a # 2/3 y # 4.

Busqué una fuente reciente (3.11) y noté que este comentario ha cambiado mientras tanto:

/**
 * oom_badness - heuristic function to determine which candidate task to kill
 *
 * The heuristic for determining which task to kill is made to be as simple and
 * predictable as possible.  The goal is to return the highest value for the
 * task consuming the most memory to avoid subsequent oom failures.
 */

Esto es un poco más explícito sobre el n. ° 2: "El objetivo es [matar] la tarea que consume la mayor cantidad de memoria para evitar fallas posteriores de OOM" y, por implicación, n. ° 4 ( "queremos matar la cantidad mínima de procesos ( uno ) ) .

Si desea ver al asesino OOM en acción, vea la nota 5.


1 Un engaño que Gilles afortunadamente me libró, ver comentarios.


2 Aquí hay un bit sencillo de C que solicita trozos de memoria cada vez más grandes para determinar cuándo fallará una solicitud de más:

#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>

#define MB 1 << 20

int main (void) {
    uint64_t bytes = MB;
    void *p = malloc(bytes);
    while (p) {
        fprintf (stderr,
            "%lu kB allocated.\n",
            bytes / 1024
        );
        free(p);
        bytes += MB;
        p = malloc(bytes);
    }
    fprintf (stderr,
        "Failed at %lu kB.\n",
        bytes / 1024
    );
    return 0;
}            

Si no conoce C, puede compilar esto gcc virtlimitcheck.c -o virtlimitchecky luego ejecutar./virtlimitcheck . Es completamente inofensivo, ya que el proceso no usa nada del espacio que solicita, es decir, en realidad nunca usa RAM.

En un sistema 3.11 x86_64 con sistema de 4 GB y 6 GB de intercambio, fallé a ~ 7400000 kB; el número fluctúa, por lo que quizás el estado sea un factor. Esto es por casualidad cerca de la CommitLimitde /proc/meminfo, pero esto a través de la modificaciónvm.overcommit_ratio no hace ninguna diferencia. Sin embargo, en un sistema ARM 448 MB 3.6.11 de 32 bits con 64 MB de intercambio, fallo a ~ 230 MB. Esto es interesante ya que en el primer caso la cantidad es casi el doble de la cantidad de RAM, mientras que en el segundo es aproximadamente 1/4, lo que implica que la cantidad de intercambio es un factor. Esto se confirmó al desactivar el intercambio en el primer sistema, cuando el umbral de falla bajó a ~ 1.95 GB, una relación muy similar a la pequeña caja ARM.

¿Pero es esto realmente por proceso? Parece ser. El breve programa a continuación solicita un fragmento de memoria definido por el usuario y, si tiene éxito, espera a que presione la tecla de retorno; de esta manera puede probar varias instancias simultáneas:

#include <stdio.h>
#include <stdlib.h>

#define MB 1 << 20

int main (int argc, const char *argv[]) {
    unsigned long int megabytes = strtoul(argv[1], NULL, 10);
    void *p = malloc(megabytes * MB);
    fprintf(stderr,"Allocating %lu MB...", megabytes);
    if (!p) fprintf(stderr,"fail.");
    else {
        fprintf(stderr,"success.");
        getchar();
        free(p);
    }
    return 0;
}

Sin embargo, tenga en cuenta que no se trata estrictamente de la cantidad de RAM e intercambio independientemente del uso; consulte la nota 5 para ver las observaciones sobre los efectos del estado del sistema.


3 se CommitLimit refiere a la cantidad de espacio de direcciones permitido para el sistema cuando vm.overcommit_memory = 2. Presumiblemente, entonces, la cantidad que puede asignar debería ser menos menos lo que ya está comprometido, que aparentemente es el Committed_AScampo.

Un experimento potencialmente interesante que demuestra esto es agregar #include <unistd.h>a la parte superior de virtlimitcheck.c (ver nota al pie 2), y fork()justo antes del while()ciclo. No se garantiza que funcione como se describe aquí sin una sincronización tediosa, pero hay una buena posibilidad de que lo haga, YMMV:

> sysctl vm.overcommit_memory=2
vm.overcommit_memory = 2
> cat /proc/meminfo | grep Commit
CommitLimit:     9231660 kB
Committed_AS:    3141440 kB
> ./virtlimitcheck 2&> tmp.txt
> cat tmp.txt | grep Failed
Failed at 3051520 kB.
Failed at 6099968 kB.

Esto tiene sentido: al mirar tmp.txt en detalle, puede ver que los procesos alternan sus asignaciones cada vez más grandes (esto es más fácil si arroja el pid en la salida) hasta que uno, evidentemente, ha reclamado lo suficiente como para que el otro falle. El ganador es libre de agarrar todo hasta CommitLimitmenos Committed_AS.


4 Vale la pena mencionar, en este punto, si aún no comprende el direccionamiento virtual y la paginación de demanda, lo que hace posible un compromiso excesivo en primer lugar es que lo que el núcleo asigna a los procesos del usuario no es en absoluto memoria física: es espacio de direcciones virtuales . Por ejemplo, si un proceso reserva 10 MB para algo, se presenta como una secuencia de direcciones (virtuales), pero esas direcciones aún no corresponden a la memoria física. Cuando se accede a dicha dirección, esto da como resultado un error de páginay luego el núcleo intenta mapearlo en la memoria real para que pueda almacenar un valor real. Los procesos generalmente reservan mucho más espacio virtual del que realmente acceden, lo que permite que el núcleo haga el uso más eficiente de la RAM. Sin embargo, la memoria física sigue siendo un recurso finito y, cuando se ha asignado todo al espacio de direcciones virtuales, se debe eliminar parte del espacio de direcciones virtuales para liberar algo de RAM.


5 Primero una advertencia : si intenta hacer esto vm.overcommit_memory=0, asegúrese de guardar su trabajo primero y cierre todas las aplicaciones críticas, porque el sistema se congelará durante ~ 90 segundos y algunos procesos morirán.

La idea es ejecutar una bomba de horquilla que agota el tiempo de espera después de 90 segundos, con las horquillas asignando espacio y algunas de ellas escribiendo grandes cantidades de datos en la RAM, todo el tiempo informando a stderr.

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/time.h>
#include <errno.h>
#include <string.h>

/* 90 second "Verbose hungry fork bomb".
Verbose -> It jabbers.
Hungry -> It grabs address space, and it tries to eat memory.

BEWARE: ON A SYSTEM WITH 'vm.overcommit_memory=0', THIS WILL FREEZE EVERYTHING
FOR THE DURATION AND CAUSE THE OOM KILLER TO BE INVOKED.  CLOSE THINGS YOU CARE
ABOUT BEFORE RUNNING THIS. */

#define STEP 1 << 30 // 1 GB
#define DURATION 90

time_t now () {
    struct timeval t;
    if (gettimeofday(&t, NULL) == -1) {
        fprintf(stderr,"gettimeofday() fail: %s\n", strerror(errno));
        return 0;
    }
    return t.tv_sec;
}

int main (void) {
    int forks = 0;
    int i;
    unsigned char *p;
    pid_t pid, self;
    time_t check;
    const time_t start = now();
    if (!start) return 1;

    while (1) {
    // Get our pid and check the elapsed time.
        self = getpid();
        check = now();
        if (!check || check - start > DURATION) return 0;
        fprintf(stderr,"%d says %d forks\n", self, forks++);
    // Fork; the child should get its correct pid.
        pid = fork();
        if (!pid) self = getpid();
    // Allocate a big chunk of space.
        p = malloc(STEP);
        if (!p) {
            fprintf(stderr, "%d Allocation failed!\n", self);
            return 0;
        }
        fprintf(stderr,"%d Allocation succeeded.\n", self);
    // The child will attempt to use the allocated space.  Using only
    // the child allows the fork bomb to proceed properly.
        if (!pid) {
            for (i = 0; i < STEP; i++) p[i] = i % 256;
            fprintf(stderr,"%d WROTE 1 GB\n", self);
        }
    }
}                        

Compila esto gcc forkbomb.c -o forkbomb. Primero, pruébalo sysctl vm.overcommit_memory=2, probablemente obtendrás algo como:

6520 says 0 forks
6520 Allocation succeeded.
6520 says 1 forks
6520 Allocation succeeded.
6520 says 2 forks
6521 Allocation succeeded.
6520 Allocation succeeded.
6520 says 3 forks
6520 Allocation failed!
6522 Allocation succeeded.

En este entorno, este tipo de bomba tenedor no llega muy lejos. Tenga en cuenta que el número en "dice N forks" no es el número total de procesos, es el número de procesos en la cadena / rama que conduce a ese.

Ahora pruébalo con vm.overcommit_memory=0. Si redirige stderr a un archivo, puede hacer un análisis crudo después, por ejemplo:

> cat tmp.txt | grep failed
4641 Allocation failed!
4646 Allocation failed!
4642 Allocation failed!
4647 Allocation failed!
4649 Allocation failed!
4644 Allocation failed!
4643 Allocation failed!
4648 Allocation failed!
4669 Allocation failed!
4696 Allocation failed!
4695 Allocation failed!
4716 Allocation failed!
4721 Allocation failed!

Solo 15 procesos no pudieron asignar 1 GB, lo que demuestra que la heurística para overcommit_memory = 0 se ve afectada por el estado. ¿Cuántos procesos hubo? Mirando al final de tmp.txt, probablemente> 100,000. Ahora, ¿cómo puede realmente usar el 1 GB?

> cat tmp.txt | grep WROTE
4646 WROTE 1 GB
4648 WROTE 1 GB
4671 WROTE 1 GB
4687 WROTE 1 GB
4694 WROTE 1 GB
4696 WROTE 1 GB
4716 WROTE 1 GB
4721 WROTE 1 GB

Ocho, lo que nuevamente tiene sentido, ya que en ese momento tenía ~ 3 GB de RAM libre y 6 GB de intercambio.

Eche un vistazo a los registros de su sistema después de hacer esto. Debería ver los puntajes de informes del asesino OOM (entre otras cosas); presumiblemente esto se relaciona con oom_badness.

encerrada dorada
fuente
el intercambio no es una solución (o incluso relacionada) a la memoria sobre el compromiso. La asignación de memoria (p. Ej .: malloc) consiste en solicitar que se reserve una memoria virtual, no física.
jlliagre
1
@jillagre: "el intercambio no es una solución (o incluso relacionada) a la memoria sobre el compromiso" -> Sí, en realidad lo es. Las páginas que se usan con poca frecuencia se intercambian de la RAM, dejando más RAM disponible para lidiar con las fallas de la página causadas por la paginación / asignación de la demanda (que es el mecanismo que hace posible el compromiso excesivo). Es posible que las páginas intercambiadas también tengan que volver a paginarse en RAM en algún momento.
Ricitos de oro
"La asignación de memoria (por ejemplo: malloc) se trata de solicitar que se reserve la memoria virtual, no la física". -> Correcto, pero el núcleo podría (y, opcionalmente, lo hará) decir no cuando no quedan asignaciones físicas . Ciertamente no sería porque un proceso se haya quedado sin espacio de direcciones virtuales (o al menos no generalmente, ya que eso también es posible, al menos en sistemas de 32 bits).
Ricitos de oro
La búsqueda de demanda no es lo que hace posible la memoria sobre el compromiso. Linux ciertamente sobreescribe la memoria en sistemas sin área de intercambio en absoluto. Puede estar confundiendo la memoria sobre el compromiso y la paginación de la demanda. Si Linux dice "no" a malloc con un proceso de 64 bits, es decir, si no está configurado para comprometerse siempre, sería debido a la corrupción de la memoria o a la suma de todas las reservas de memoria (ya sea asignadas o no a RAM o disco) está por encima de un umbral umbral según la configuración. Esto no tiene nada que ver con el uso de RAM, ya que puede ocurrir incluso cuando todavía hay RAM libre.
jlliagre
"La paginación de demanda no es lo que hace posible la memoria sobre el compromiso". -> Quizás sería mejor decir que es un direccionamiento virtual que hace posible tanto la paginación de demanda como el exceso de compromiso. "Linux ciertamente sobreescribe la memoria en sistemas sin área de intercambio". -> Obviamente, ya que la paginación de demanda no requiere intercambio; La paginación de demanda de intercambio es solo una instancia especial de paginación de demanda. Una vez más, el intercambio es una solución al exceso de compromiso, no en el sentido de que resuelve el problema, sino en el sentido de que ayudará a prevenir posibles eventos de OOM que podrían resultar de un compromiso excesivo.
Ricitos de oro
16

Esto no le sucederá si solo carga 1G de datos en la memoria. ¿Qué pasa si cargas mucho, mucho más? Por ejemplo, a menudo trabajo con archivos enormes que contienen millones de probabilidades que deben cargarse en R. Esto toma alrededor de 16 GB de RAM.

Ejecutar el proceso anterior en mi computadora portátil hará que comience a intercambiarse como loco tan pronto como se hayan llenado mis 8 GB de RAM. Eso, a su vez, ralentizará todo porque leer desde el disco es mucho más lento que leer desde la RAM. ¿Qué sucede si tengo una computadora portátil con 2 GB de RAM y solo 10 GB de espacio libre? Una vez que el proceso ha tomado toda la RAM, también llenará el disco porque está escribiendo para intercambiar y me queda sin más RAM y sin más espacio para intercambiar (las personas tienden a limitar el intercambio a una partición dedicada en lugar de a archivo de intercambio exactamente por esa razón). Ahí es donde entra el asesino OOM y comienza a matar procesos.

Entonces, el sistema puede quedarse sin memoria. Además, los sistemas de intercambio excesivo pueden volverse inutilizables mucho antes de que esto suceda simplemente debido a las lentas operaciones de E / S debido al intercambio. En general, se quiere evitar el intercambio tanto como sea posible. Incluso en servidores de gama alta con SSD rápidos, hay una clara disminución en el rendimiento. En mi computadora portátil, que tiene una unidad clásica de 7200 RPM, cualquier intercambio significativo esencialmente deja el sistema inutilizable. Cuanto más intercambia, más lento se vuelve. Si no elimino el proceso ofensivo rápidamente, todo se bloquea hasta que interviene el asesino OOM.

terdon
fuente
5

Los procesos no se eliminan cuando no hay más RAM, se eliminan cuando se los ha engañado de esta manera:

  • El kernel de Linux comúnmente permite que los procesos asignen (es decir, reserven) una cantidad de memoria virtual que es más grande de lo que realmente está disponible (parte de RAM + toda el área de intercambio)
  • Mientras los procesos solo accedan a un subconjunto de las páginas que han reservado, todo funciona bien.
  • si después de un tiempo, un proceso intenta acceder a una página que posee pero no hay más páginas libres, se produce una situación de falta de memoria
  • El asesino de OOM selecciona uno de los procesos, no necesariamente el que solicitó una nueva página, y simplemente lo mata para recuperar la memoria virtual.

Esto puede ocurrir incluso mientras el sistema no está intercambiando activamente, por ejemplo, si el área de intercambio está llena de páginas de memoria de demonios dormidos.

Esto nunca sucede en sistemas operativos que no comprometen demasiado la memoria. Con ellos, no se elimina ningún proceso aleatorio, pero el primer proceso que solicita memoria virtual mientras está agotado tiene malloc (o similar) que vuelve por error. Por lo tanto, se le da la oportunidad de manejar adecuadamente la situación. Sin embargo, en estos sistemas operativos, también puede ocurrir que el sistema se quede sin memoria virtual mientras todavía hay RAM libre, lo cual es bastante confuso y generalmente mal entendido.

jlliagre
fuente
3

Cuando se agota la RAM disponible, el núcleo comienza a intercambiar bits de procesamiento en el disco. En realidad, el núcleo comienza a intercambiar a cuando la RAM está a punto de agotarse: comienza a intercambiar de manera proactiva cuando tiene un momento de inactividad, para responder mejor si una aplicación de repente requiere más memoria.

Tenga en cuenta que la RAM no se usa solo para almacenar la memoria de los procesos. En un sistema saludable típico, los procesos usan solo la mitad de la RAM, y la otra mitad se usa para caché de disco y buffers. Esto proporciona un buen equilibrio entre los procesos en ejecución y la entrada / salida de archivos.

El espacio de intercambio no es infinito. En algún momento, si los procesos siguen asignando más y más memoria, los datos indirectos de la RAM llenarán el intercambio. Cuando eso sucede, los procesos que intentan solicitar más memoria ven su solicitud denegada.

Por defecto, Linux sobrecompite la memoria. Esto significa que a veces permitirá que un proceso se ejecute con la memoria que ha reservado, pero que no se utiliza. La razón principal para tener un compromiso excesivo es la forma en que funciona la bifurcación . Cuando un proceso inicia un subproceso, el proceso secundario opera conceptualmente en una réplica de la memoria del padre: los dos procesos inicialmente tienen memoria con el mismo contenido, pero ese contenido divergerá a medida que los procesos hagan cambios cada uno en su propio espacio. Para implementar esto completamente, el núcleo tendría que copiar toda la memoria del padre. Esto haría que la bifurcación fuera lenta, por lo que el núcleo practica copia en escritura: inicialmente, el niño comparte toda su memoria con el padre; cada vez que cualquiera de los procesos escribe en una página compartida, el núcleo crea una copia de esa página para interrumpir el intercambio.

A menudo, un niño dejará muchas páginas intactas. Si el núcleo asignara suficiente memoria para replicar el espacio de memoria del padre en cada bifurcación, se desperdiciaría mucha memoria en las reservas que los procesos secundarios nunca usarán. Por lo tanto, sobrecompromiso: el núcleo solo reserva parte de esa memoria, en base a una estimación de cuántas páginas necesitará el niño.

Si un proceso intenta asignar algo de memoria y no queda suficiente memoria, el proceso recibe una respuesta de error y lo trata como mejor le parezca. Si un proceso solicita memoria indirectamente al escribir en una página compartida que no se debe compartir, es una historia diferente. No hay forma de informar esta situación a la aplicación: cree que tiene datos que se pueden escribir allí, e incluso podría leerlos; es solo que la escritura implica una operación un poco más elaborada bajo el capó. Si el núcleo no puede proporcionar una nueva página de memoria, todo lo que puede hacer es eliminar el proceso de solicitud o eliminar algún otro proceso para llenar la memoria.

Podría pensar en este punto que matar el proceso de solicitud es la solución obvia. Pero en la práctica, esto no es tan bueno. El proceso puede ser importante y ahora solo necesita acceder a una de sus páginas, mientras que puede haber otros procesos menos importantes en ejecución. Entonces, el núcleo incluye heurísticas complejas para elegir qué procesos matar: el (in) famoso asesino OOM .

Gilles 'SO- deja de ser malvado'
fuente
2

Solo para agregar otro punto de vista de las otras respuestas, muchos VPS alojan varias máquinas virtuales en cualquier servidor. Cualquier VM individual tendrá una cantidad específica de RAM para su propio uso. Muchos proveedores ofrecen "RAM en ráfaga", en la que pueden usar RAM más allá de la cantidad que están designados. Esto está destinado a ser solo para uso a corto plazo, y aquellos que van más allá de esta cantidad de tiempo prolongada pueden ser penalizados por los procesos de eliminación del host para reducir la cantidad de RAM en uso para que otros no sufran La máquina host está sobrecargada.

agweber
fuente
-1

Algún tiempo, Linux ocupa un espacio virtual externo. Esa es la partición de intercambio. Cuando se llena Ram, Linux toma esta área de intercambio para ejecutar un proceso de baja prioridad.

Bizzon
fuente
1
No se ejecuta ningún proceso desde el intercambio. La memoria virtual se divide en unidades distintas de igual tamaño llamadas páginas. Cuando se libera memoria física, las páginas de baja prioridad son expulsadas de la RAM. Si bien las páginas en el caché de archivos tienen respaldo del sistema de archivos, las páginas anónimas deben almacenarse en intercambio. La prioridad de una página no está directamente relacionada con la prioridad del proceso al que pertenece, sino con qué frecuencia se usa. Si un proceso en ejecución intenta acceder a una página que no está en la memoria física, se genera un error de página y el proceso se adelanta a favor de otro proceso mientras las páginas necesarias se obtienen del disco.
Thomas Nyman