Chcę utworzyć program, który będzie symulował sytuację braku pamięci (OOM) na serwerze Unix. Stworzyłem ten super prosty pożeracz pamięci:
#include <stdio.h>
#include <stdlib.h>
unsigned long long memory_to_eat = 1024 * 50000;
size_t eaten_memory = 0;
void *memory = NULL;
int eat_kilobyte()
{
memory = realloc(memory, (eaten_memory * 1024) + 1024);
if (memory == NULL)
{
// realloc failed here - we probably can't allocate more memory for whatever reason
return 1;
}
else
{
eaten_memory++;
return 0;
}
}
int main(int argc, char **argv)
{
printf("I will try to eat %i kb of ram\n", memory_to_eat);
int megabyte = 0;
while (memory_to_eat > 0)
{
memory_to_eat--;
if (eat_kilobyte())
{
printf("Failed to allocate more memory! Stucked at %i kb :(\n", eaten_memory);
return 200;
}
if (megabyte++ >= 1024)
{
printf("Eaten 1 MB of ram\n");
megabyte = 0;
}
}
printf("Successfully eaten requested memory!\n");
free(memory);
return 0;
}
Zjada tyle pamięci, ile zdefiniowano, w memory_to_eat
której teraz jest dokładnie 50 GB pamięci RAM. Alokuje pamięć o 1 MB i drukuje dokładnie punkt, w którym nie może przydzielić więcej, dzięki czemu wiem, jaką maksymalną wartość udało mu się zjeść.
Problem w tym, że to działa. Nawet w systemie z 1 GB pamięci fizycznej.
Kiedy sprawdzam górę, widzę, że proces zjada 50 GB pamięci wirtualnej i tylko mniej niż 1 MB pamięci rezydentnej. Czy istnieje sposób na stworzenie pożeracza pamięci, który naprawdę ją pochłania?
Specyfikacje systemu: jądro Linuksa 3.16 ( Debian ) najprawdopodobniej z włączonym overcommitem (nie wiem jak to sprawdzić) bez wymiany i zwirtualizowane.
sysctl -w vm.overcommit_memory=2
jako root; zobacz mjmwired.net/kernel/Documentation/vm/overcommit-accounting . Pamiętaj, że może to mieć inne konsekwencje; w szczególności bardzo duże programy (np. przeglądarka internetowa) mogą nie uruchamiać programów pomocniczych (np. czytnik PDF).