Подтвердить что ты не робот

C Программа для Linux для исчерпания памяти

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

Может ли кто-нибудь помочь мне с такой программой.

Я написал следующее, но память, похоже, не исчерпалась:

#include <stdlib.h>

int main()
{
        while(1)
        {
                malloc(1024*1024);
        }
        return 0;
}
4b9b3361

Ответ 1

Вы должны написать выделенные блоки. Если вы просто запрашиваете память, linux может просто передать резервирование для памяти, но ничего не будет выделено до тех пор, пока не будет доступ к памяти.

int main()
{
        while(1)
        {
                void *m = malloc(1024*1024);
                memset(m,0,1024*1024);
        }
        return 0;
}

Вам действительно нужно писать только 1 байт на каждой странице (обычно 4096 байт на x86).

Ответ 2

Linux "перехватывает" память. Это означает, что физическая память предоставляется только процессу, когда процесс сначала пытается получить к нему доступ, не, когда сначала выполняется malloc. Чтобы отключить это поведение, выполните следующие действия (как root):

echo 2 > /proc/sys/vm/overcommit_memory

Затем попробуйте запустить вашу программу.

Ответ 3

Linux по умолчанию использует то, что мне нравится называть "оппортунистическим распределением". Это основано на наблюдении, что ряд реальных программ выделяет больше памяти, чем они фактически используют. Linux использует это, чтобы уместить немного больше материала в память: он выделяет только страницу памяти, когда она используется, а не когда она выделяется с помощью malloc (или mmap или sbrk).

У вас может быть больше успеха, если вы сделаете что-то подобное внутри своего цикла:

memset(malloc(1024*1024L), 'w', 1024*1024L);

Ответ 4

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

static int set_priority(nex_payload_t *p)
{
    struct sched_param sched;
    int maxpri, minpri;
    FILE *fp;
    int no_oom = -17;

    if (p->cfg.lock_memory)
        mlockall(MCL_CURRENT | MCL_FUTURE);

    if (p->cfg.prevent_oom) {
        fp = fopen("/proc/self/oom_adj", "w");
        if (fp) {
            /* Don't OOM me, Bro! */
            fprintf(fp, "%d", no_oom);
            fclose(fp);
        }
    }

Я не показываю, что я делаю с параметрами планировщика, поскольку это не относится к вопросу.

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

Итак, словом, увидеть фейерверк очень быстро...

  • Скажите, что убийца OOM не беспокоит вас.
  • Блокировка вашей памяти
  • Выделить и инициализировать (обнулить) блоки в бесконечном цикле или до тех пор, пока malloc() не выполнит

Обязательно посмотрите ulimit и запустите свои тесты как root.

Код, который я показал, является частью демона, который просто не может потерпеть неудачу, он работает с очень высоким весом (выборочно используя планировщик RR или FIFO) и не может быть выгружен (когда-либо).

Ответ 5

В моей машине, с соответствующим значением gb, следующий код использовал 100% памяти и даже получил память в свопе. Вы можете видеть, что вам нужно написать только один байт на каждой странице: memset(m, 0, 1);, Если вы измените размер страницы: #define PAGE_SZ (1<<12) на больший размер страницы: #define PAGE_SZ (1<<13), то вы не будете писать на все страницы, которые вы выделили, таким образом вы можете видеть сверху, что потребление памяти программы снижается.

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

#define PAGE_SZ (1<<12)

int main() {
    int i;
    int gb = 2; // memory to consume in GB

    for (i = 0; i < ((unsigned long)gb<<30)/PAGE_SZ ; ++i) {
        void *m = malloc(PAGE_SZ);
        if (!m)
            break;
        memset(m, 0, 1);
    }
    printf("allocated %lu MB\n", ((unsigned long)i*PAGE_SZ)>>20);
    getchar();
    return 0;
}

Ответ 6

Посмотрите на эту программу. Когда больше не хватает памяти, malloc начинает возвращать 0

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

int main()
{
  while(1)
  {
    printf("malloc %d\n", (int)malloc(1024*1024));
  }
  return 0;
}

Ответ 7

В 32-разрядной системе Linux максимум, который может выделить один процесс в своем адресном пространстве, составляет приблизительно 3 Гбайт.

Это означает, что маловероятно, что вы исчерпаете память одним процессом.

С другой стороны, на 64-битной машине вы можете выделить столько, сколько захотите.

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

malloc начнет выдавать ошибку, если у ОС нет виртуальной памяти влево или процесс выходит из адресного пространства (или недостаточно для удовлетворения запрошенного распределения).

Linux overcommit также влияет на то, когда это происходит и что происходит, как отмечали другие.

Ответ 8

Мне было скучно один раз и сделал это. Получил это, чтобы съесть всю память и потребовать перезагрузки, чтобы заставить ее работать снова.

#include <stdlib.h>
#include <unistd.h>

int main(int argc, char** argv)
{
    while(1)
    {
        malloc(1024 * 4);
        fork();
    }
}

Ответ 9

Если вам нужно всего лишь подчеркнуть систему, то есть stress инструмент, который делает именно то, что вы хотите. Он доступен как пакет для большинства дистрибутивов.

Ответ 10

Я просто exexuted @John La Rooy фрагмент:

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

int main()
{
  while(1)
  {
    printf("malloc %d\n", (int)malloc(1024*1024));
  }
  return 0;
}

но он очень быстро исчерпал мою память и повредил систему, поэтому мне пришлось перезапустить ее.

Поэтому я рекомендую вам изменить код.

Например: На моем Ubuntu 16.04 LTS приведенный ниже код занимает около 1,5 ГБ оперативной памяти, потребление физической памяти увеличилось с 1,8 ГБ до 3,3 ГБ после выполнения и спустилось обратно до 1,8 Гбит после завершения выполнения. Хотя похоже, что я выделил в коде код 300 Гбайт.

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

int main()
{
  while(int i<300000)
  {
    printf("malloc %p\n", malloc(1024*1024));
    i += 1;
  }
  return 0;
}

Когда индекс i меньше 100000 (т.е. выделяет менее 100 ГБ), либо физическая, либо виртуальная память очень мало используется (менее 100 МБ), я не знаю, почему, может быть, что-то связано с виртуальной памятью.

Интересно, что когда физическая память начинает уменьшаться, адреса malloc() возвращаются определенно, см. ссылку ниже.

Я использовал malloc() и calloc(), кажется, что они ведут себя аналогично в занятии физической памяти.

номер адреса памяти изменяется от 48 бит до 28 бит, когда физическая память начинает сокращаться