Чи може Linux «закінчитися оперативною пам’яттю»?


20

У мережі Інтернет я побачив декілька публікацій, які, очевидно, скаржаться на несподівано вбиті процеси VPS, оскільки вони використовували занадто багато оперативної пам'яті.

Як це можливо? Я подумав, що всі сучасні ОС 'забезпечують' нескінченну оперативну пам’ять ', просто використовуючи диски підкачки для того, що переходить фізичну оперативну пам'ять. Це правильно?

Що може статися, якщо процес "знищений через низьку оперативну пам'ять"?


12
Жодна ОС не має нескінченної оперативної пам’яті. Окрім фізичних чіпів оперативної пам’яті в машині, ОС може - як правило, необов’язково - використовувати так званий 'файл swap', який знаходиться на диску. Коли комп'ютеру потрібно більше пам'яті, ніж у пам'яті RAM, він заміняє деякі файли на файл swap. Але коли файл swap досягає його ємності - або тому, що ви встановили максимальний розмір (типовий) або диск заповнюється - у вас не вистачає віртуальної пам'яті.
Джон Дайблінг

@JohnDibling; тож чи є якась причина, щоб хотілося обмежити розмір swap, крім того, щоб заощадити на диску диск для файлової системи? Іншими словами, якщо у мене диск із 20 ГБ і лише 1 ГБ файлів, чи є якась причина не встановити розмір свого розміру на 19 ГБ?
тематична помилка

1
Для спрощення речей я б сказав, що дві причини обмеження розміру свопу - це 1) зменшення споживання диска та 2) підвищення продуктивності. Останнє може бути вірніше в Windows, ніж / * NIX, але знову ж таки, якщо ви використовуєте простір для обміну на диску, продуктивність буде знижена. Доступ до диска або повільніше, ніж ОЗУ, або набагато повільніше, ніж ОЗУ, залежно від системи.
Джон Дайблінг

9
Swap - це не оперативна пам'ять . en.wikipedia.org/wiki/Random-access_memory Обсяг оперативної пам’яті у вашій системі - це кількість оперативної пам’яті у вашій системі - період. Це не неоднозначний чи динамічний обсяг. Це абсолютно зафіксовано. "Пам'ять" - це більш неоднозначне поняття, але відмінність оперативної пам'яті від інших форм зберігання даних, як вказує тердон (+1), досить значна. Заміна диска не може замінити продуктивність оперативної пам’яті на багато порядків . Система, яка надмірно залежить від заміни, в кращому випадку тимчасова і взагалі: сміття.
goldilocks

1
Тож дисковий простір зараз нескінченний?
Каз

Відповіді:


41

Що може статися, якщо процес "знищений через низьку оперативну пам'ять"?

Іноді кажуть, що за замовчуванням Linux ніколи не відмовляє в запитах на отримання більшої кількості пам'яті з коду програми - наприклад malloc(). 1 Це насправді не так; за замовчуванням використовується евристика, згідно з якою

Очевидне перевиконання адресного простору відмовляється. Використовується для типової системи. Це забезпечує серйозну помилку розподілу, дозволяючи перевиконати комісію для зменшення використання свопів.

З [linux_src]/Documentation/vm/overcommit-accounting(усі цитати з дерева 3,11). Точно те, що вважається "серйозно диким виділенням", не є явним, тому нам доведеться пройти джерело, щоб визначити деталі. Ми також могли б використати експериментальний метод у виносці 2 (нижче), щоб спробувати отримати деяке евристичне відображення - виходячи з цього, моє первісне емпіричне спостереження полягає в тому, що при ідеальних обставинах (== система не працює), якщо ви не ' не матимете жодного свопу, вам буде дозволено виділити близько половини оперативної пам’яті, а якщо у вас є підміна, ви отримаєте приблизно половину своєї оперативної пам’яті плюс усю свопу. Це більше або менше на кожен процес (але зауважте, що ця межа є динамічною і може змінюватися через стан, див. Деякі спостереження у виносці 5).

Половина вашої оперативної пам’яті плюс своп - явно за замовчуванням для поля «Команда ліміту» в /proc/meminfo. Ось що це означає - і зауважте, що насправді це не має нічого спільного з межею, щойно обговорюваною (з [src]/Documentation/filesystems/proc.txt):

CommitLimit: Виходячи з коефіцієнта перевиконання ('vm.overcommit_ratio'), це загальний обсяг пам’яті, який зараз можна розподілити в системі. Цього ліміту дотримується лише в тому випадку, якщо включений суворий облік перевиконання (режим 2 у "vm.overcommit_memory"). CommLimit обчислюється за такою формулою: CommitLimit = ('vm.overcommit_ratio' * Physical RAM) + Swap Наприклад, у системі з 1G фізичної оперативної пам’яті та 7G свопу з 'vm.overcommit_ratio' 30, це дасть Комісія лінійки 7.3G.

У раніше цитованому документі з доповіддю з бухгалтерського обліку зазначається, що за замовчуванням vm.overcommit_ratioдорівнює 50. Тож якщо sysctl vm.overcommit_memory=2ви можете, то можете налаштувати vm.covercommit_ratio (with sysctl) і побачити наслідки. 3 Режим за замовчуванням, коли CommitLimitвін не застосовується і відмовляються лише "явні перевиконання адресного простору", - це коли vm.overcommit_memory=0.

У той час як стратегія за замовчуванням має евристичний обмеження на процес, що запобігає "серйозно дикому виділенню", вона залишає систему в цілому вільною, щоб отримати серйозну дикість, а також розподілити розумно. 4 Це означає, що в якийсь момент у неї може закінчитися пам'ять, і доведеться оголосити про банкрутство певного процесу через убивцю ООМ .

Що вбиває вбивцю ООМ? Це не обов'язково той процес, який вимагав пам'яті, коли його не було, оскільки це не обов'язково справді винен процес, і що ще важливіше, не обов'язково той, який найшвидше позбавить систему від проблеми, в якій знаходиться.

Це цитується звідси, що, ймовірно, цитує джерело 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)
 */

Що здається гідним обґрунтуванням. Однак, не отримуючи судово-медичної експертизи, №5 (що є надмірним №1) здається мудрим впровадженням продажу, а №3 - зайвим №2. Тому може бути доцільним вважати це зведеним до №2 / 3 та №4.

Я проглянув нещодавнє джерело (3.11) і помітив, що цей коментар змінився тимчасово:

/**
 * 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.
 */

Це трохи виразніше щодо №2: "Мета - [вбити] завдання, що споживає найбільше пам’яті, щоб уникнути наступних невдач уомі", і за наслідком №4 ( "ми хочемо вбити мінімальну кількість процесів ( один )" ) .

Якщо ви хочете побачити вбивцю OOM в дії, див. Виноску 5.


1 Зман Жилла, на щастя, позбавив мене, дивіться коментарі.


2 Ось простий біт C, який запитує все більші шматки пам’яті, щоб визначити, коли запит на отримання додаткового помилки не вийде:

#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;
}            

Якщо ви не знаєте C, можете скласти це gcc virtlimitcheck.c -o virtlimitcheck, а потім запустіть ./virtlimitcheck. Це абсолютно нешкідливо, оскільки процес не використовує жоден простір, який він вимагає - тобто, він ніколи не використовує жодної ОЗУ.

У системі 3,11 x86_64 із системою 4 ГБ та 6 ГБ свопу, я не вдався до ~ 7400000 кБ; число коливається, тому, можливо, стан є фактором. Це збігом близько до CommitLimitдюйма /proc/meminfo, але зміна цього з допомогою vm.overcommit_ratioробить ніякої різниці. У 3.6.11 32-бітовій системі 448 Мб ARM з 64 МБ свопів, однак, я не виходить при ~ 230 МБ. Це цікаво, оскільки в першому випадку сума майже вдвічі перевищує об'єм оперативної пам’яті, тоді як у другому це приблизно 1/4, що - сильно означає, що обмін свопом є фактором. Це було підтверджено вимкненням swap у першій системі, коли поріг відмови знизився до ~ 1,95 ГБ, що дуже схоже відношення до маленької коробки ARM.

Але чи це насправді за один процес? Здається, є. Коротка програма, подана нижче, запитує певний користувачем шматок пам'яті, і якщо це вдасться, чекає, коли ви повернетесь - таким чином ви можете спробувати кілька одночасних екземплярів:

#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;
}

Однак остерігайтеся, що мова йде не лише про кількість оперативної пам’яті та своп незалежно від використання - див. Виноску 5 для спостережень за наслідками стану системи.


3 CommitLimit посилається на кількість адресного простору, дозволеного для системи, коли vm.overcommit_memory = 2. Імовірно, тоді сума, яку ви можете виділити, повинна бути такою, мінус що вже зроблено, що, мабуть, Committed_ASполе.

Потенційно цікавим експериментом, що демонструє це, є додавання #include <unistd.h>до вершини virtlimitcheck.c (див. Виноску 2) та fork()праворуч перед while()циклом. Це не гарантує роботу, як описано тут, без копіткої синхронізації, але є гідний шанс, що це буде, 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.

Це має сенс - детально дивлячись на tmp.txt, ви можете бачити, як процеси чергуються їх більші та більші виділення (це простіше, якщо ви кинете під у вихід), поки один, очевидно, не стверджує достатньо, що інший не працює. Тоді переможець може безкоштовно схопити все до CommitLimitмінуса Committed_AS.


4 У цьому моменті варто згадати, якщо ви вже не розумієте віртуальну адресацію та підказка з вимогою, що в першу чергу можливе перевиконання зобов’язань - це те, що ядро ​​виділяє для процесів користувальницької роботи - це зовсім не фізична пам'ять - це віртуальний адресний простір . Наприклад, якщо процес резервує 10 Мб для чогось, це викладається як послідовність (віртуальних) адрес, але ці адреси ще не відповідають фізичній пам'яті. Коли доступ до такої адреси, це призводить до помилки сторінкиа потім ядро ​​намагається відобразити його на реальній пам'яті, щоб воно могло зберігати реальне значення. Процеси зазвичай резервують набагато більше віртуального простору, ніж вони фактично отримують доступ, що дозволяє ядру максимально ефективно використовувати ОЗУ. Однак фізична пам’ять все ще є кінцевим ресурсом, і коли все це було зіставлено у віртуальний адресний простір, потрібно звільнити деякий віртуальний адресний простір, щоб звільнити деяку оперативну пам'ять.


5 Перше попередження : Якщо ви спробуєте це vm.overcommit_memory=0, спочатку збережіть свою роботу та закрийте будь-які критичні програми, оскільки система буде заморожена на ~ 90 секунд, і деякий процес загине!

Ідея полягає у тому, щоб запустити вилкову бомбу, яка вичерпується через 90 секунд, при цьому вилки виділяють простір, а деякі з них записують велику кількість даних в оперативну пам'ять, весь час звітуючи перед 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);
        }
    }
}                        

Складіть це gcc forkbomb.c -o forkbomb. По-перше, спробуйте sysctl vm.overcommit_memory=2- ви, ймовірно, отримаєте щось на кшталт:

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.

У цьому середовищі до цього виду бомбовика не дуже далеко. Зауважте, що число у "каже N forks" - не загальна кількість процесів, це кількість процесів у ланцюзі / гілці, що веде до цього.

Тепер спробуйте vm.overcommit_memory=0. Якщо ви перенаправляєте stderr на файл, після цього ви можете зробити якийсь сирий аналіз, наприклад:

> 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!

Тільки 15 процесів не вдалося виділити 1 ГБ - демонстрації того, що евристика для overcommit_memory = 0 буде залежить від стану. Скільки там процесів було? Переглядаючи кінець tmp.txt, ймовірно,> 100 000. Тепер, як насправді можна використовувати 1 Гб?

> 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

Вісім - що знову має сенс, оскільки на той час у мене було ~ 3 ГБ оперативної пам’яті та 6 ГБ свопу.

Перегляньте свої системні журнали після цього. Ви повинні побачити результати звітів про вбивство OOM (серед іншого); імовірно, це стосується oom_badness.


заміна не є рішенням (або навіть пов'язаним) з пам'яттю над прихильністю. Розподіл пам’яті (наприклад: malloc) - це запит віртуальної пам’яті бути зарезервованою, а не фізичною.
jlliagre

1
@jillagre: " Заміна не є рішенням (або навіть пов'язаним) з пам'яттю над прихильністю" -> Так, насправді так і є. Нечасто використовувані сторінки витісняються з оперативної пам’яті, залишаючи більше оперативної пам’яті для усунення несправностей сторінок, викликаних підказками / розподілом попиту (що є механізмом, який робить можливим перевиконання зобов’язань). На обмінені сторінки, можливо, в якийсь момент потрібно буде попросити передати повідомлення в оперативку
goldilocks

"Розподіл пам'яті (наприклад: malloc) - це прохання зарезервувати віртуальну пам'ять, а не фізичну." -> Право, але ядро ​​могло б (і необов'язково, буде) сказати "ні", коли не залишилося фізичних відображень . Це, звичайно, не буде, оскільки у віртуального адресного простору не вистачає процесу (або, принаймні, зазвичай, оскільки це теж можливо, принаймні в 32-бітних системах).
goldilocks

Пейджинг попиту - це не те, що робить можливим пам'ять над прихильністю. Linux, безумовно, більше фіксує пам'ять у системах, які взагалі не мають області обміну. Можливо, ви заплутаєте пам’ять через прихильність і вимагаєте підкачки. Якщо Linux скаже "ні", щоб розмовляти з 64-бітовим процесом, тобто якщо він не налаштований завжди перезавантажувати, це буде або через пошкодження пам'яті, або через суму всіх резервів пам'яті (зіставленим чи ні на оперативну пам'ять чи на диск) перевищує пороговий поріг залежно від конфігурації. Це не має нічого спільного з використанням оперативної пам’яті, оскільки це може статися навіть тоді, коли є ще вільна оперативна пам’ять.
jlliagre

"Пейджинг попиту - це не те, що робить можливою пам'ять над прихильністю." -> Можливо, було б краще сказати, що саме віртуальна адресація робить можливою як підписку на вимогу, так і перевиконання зобов'язань. "Linux, безумовно, переносить пам'ять на системи, які взагалі не мають області обміну". -> Очевидно, оскільки пейджинг попиту не вимагає своп; пейджинг попиту із свопом - це лише особливий екземпляр пейджингу попиту. Знову ж таки, своп - це рішення надмірної відданості, не в тому сенсі, що він вирішує проблему, а в тому сенсі, який допоможе запобігти потенційним подіям OOM, які можуть бути наслідком надмірної прихильності.
goldilocks

16

Це не станеться з вами, якщо ви коли-небудь завантажуєте в пам'ять лише 1G даних. Що робити, якщо ви завантажуєте набагато більше? Наприклад, я часто працюю з величезними файлами, що містять мільйони ймовірностей, які потрібно завантажити в Р. Це займає близько 16 ГБ оперативної пам’яті.

Запуск вищевказаного процесу на моєму ноутбуці призведе до того, що він почне мінятися як божевільний, як тільки мої 8 Гб оперативної пам’яті заповниться. Це, у свою чергу, сповільнить усе, тому що читання з диска відбувається набагато повільніше, ніж читання з ОЗУ. Що робити, якщо у мене ноутбук з 2 Гб оперативної пам’яті і лише 10 ГБ вільного місця? Після того, як процес зайняв всю оперативну пам’ять, він також заповнить диск, тому що він пише для заміни, і мені не залишається більше оперативної пам’яті і більше місця для заміни (люди, як правило, обмежують своп на виділений розділ, а не на swapfile саме з цієї причини). Ось де входить вбивця ООМ і починає процеси вбивства.

Отже, у системи дійсно може не вистачити пам'яті. Крім того, сильно поміняються системи можуть стати непридатними задовго до того, як це станеться просто через повільні операції вводу / виводу через заміну. Взагалі хочеться максимально уникати заміни. Навіть на серверах високого класу зі швидкими SSD є явне зниження продуктивності. На моєму ноутбуці, який має класичний привід 7200RPM, будь-яка значна заміна суттєво робить систему непридатною. Чим більше він міняється, тим повільніше стає. Якщо я не вбиваю процес злочину швидко, все зависає, поки не вступить вбивця OOM.


5

Процеси не вбиваються, коли більше немає оперативної пам’яті, вони вбиваються, коли їх обдурюють таким чином:

  • Ядро Linux зазвичай дозволяє процесам виділяти (тобто резервувати) кількість віртуальної пам’яті, яка більша, ніж реально доступна (частина оперативної пам’яті + вся область заміни)
  • доки процеси отримують доступ лише до підмножини сторінок, які вони зарезервували, все працює нормально.
  • якщо через деякий час процес намагається отримати доступ до сторінки, яка йому належить, але більше сторінок не є безкоштовними, виникає ситуація із пам'яттю
  • Вбивця OOM вибирає один з процесів, не обов’язково той, який вимагав нової сторінки, і просто вбиває її для відновлення віртуальної пам'яті.

Це може статися навіть тоді, коли система не активно заміняється, наприклад, якщо область заміни заповнена сторінками пам'яті демонів.

Це ніколи не відбувається на ОС, які не перенавантажують пам'ять. З ними не вбивається жоден випадковий процес, але перший процес, який запитує віртуальну пам'ять, поки вона вичерпана, малок (або подібне) повертається помилково. Таким чином, надається шанс правильно впоратися з ситуацією. Однак на цих ОС може також статися, що у системи не вистачає віртуальної пам’яті, поки все ще є вільна оперативна пам’ять, що досить заплутано і в цілому неправильно зрозуміло.


3

Коли наявна ОЗУ вичерпана, ядро ​​починає замінювати біти обробки на диск. Насправді ядро ​​починає міняти a, коли оперативна пам'ять майже вичерпана: вона починає проактивно мінятися, коли має момент простою, щоб бути більш чуйною, якщо для програми раптом потрібно більше пам’яті.

Зауважте, що оперативна пам’ять використовується не тільки для зберігання пам'яті процесів. У типовій здоровій системі для процесів використовується лише близько половини оперативної пам’яті, а інша половина використовується для кеш-диску та буферів. Це забезпечує хороший баланс між запущеними процесами та введенням / виведенням файлів.

Простір підкачки не є нескінченним. У якийсь момент, якщо процеси продовжують виділяти все більше і більше пам’яті, дані про переливання оперативної пам’яті заповнять своп. Коли це відбувається, процеси, які намагаються запитувати більше пам'яті, бачать їх запит відхиленим.

За замовчуванням Linux переповнює пам'ять. Це означає, що іноді дозволить запустити процес із пам'яттю, яку він зарезервував, але не використовував. Основною причиною перевиконання є спосіб розробки робіт. Коли процес запускає підпроцес, дочірній процес концептуально функціонує в репліку пам'яті батьків - два процеси спочатку мають пам'ять з однаковим вмістом, але цей контент буде розходитися, оскільки процеси вносять зміни кожен у своєму власному просторі. Щоб повною мірою реалізувати це, ядро ​​повинно було б скопіювати всю пам'ять батьків. Це зробить розблокування повільним, тому ядро ​​практикує копіювати при записі: спочатку дитина ділиться всією пам’яттю з батьком; щоразу, коли будь-який процес записує на загальну сторінку, ядро ​​створює копію цієї сторінки, щоб порушити спільний доступ.

Часто дитина залишає багато сторінок недоторканими. Якщо ядро ​​виділило достатню кількість пам’яті для тиражування пам’яті батька на кожній вилці, багато пам’яті витрачалося б на застереження, які дочірні процеси ніколи не збираються використовувати. Отже, перекомітування: ядро ​​залишає лише частину цієї пам’яті, грунтуючись на оцінці того, скільки сторінок знадобиться дитині.

Якщо процес намагається виділити деяку кількість пам’яті, а пам’яті не вистачає, процес отримує відповідь про помилку і розбирається з нею, як вважає за потрібне. Якщо процес опосередковано вимагає пам’яті, записуючи на загальну сторінку, яка повинна бути не наданою загальним доступом, це вже інша історія. Немає можливості повідомити про цю ситуацію в додатку: він вважає, що в ній є дані, що записуються, і навіть міг їх прочитати - це просто те, що написання передбачає дещо більш складну операцію під капотом. Якщо ядро ​​не в змозі надати нову сторінку пам'яті, все, що вона може зробити, це вбити процес запиту або вбити якийсь інший процес для заповнення пам'яті.

На даний момент ви можете подумати, що вбивство процесу запиту є очевидним рішенням. Але на практиці це не так добре. Цей процес може бути важливим, тому що зараз виникає лише необхідність доступу до однієї з його сторінок, тоді як можуть бути запущені й інші, менш важливі процеси. Тож ядро ​​включає складну евристику, щоб вибрати, які процеси вбити - (в) відомого вбивці OOM .


2

Просто для додання іншої точки зору з інших відповідей, багато VPS розміщують кілька віртуальних машин на будь-якому сервері. Будь-яка окрема VM матиме заданий об'єм оперативної пам'яті для власного використання. Багато провайдерів пропонують "розривну оперативну пам'ять", в якій вони можуть використовувати оперативну пам'ять понад суму, яку їм призначено. Це передбачається лише для короткочасного використання, і тих, хто перевищує цю кількість тривалої кількості часу, може бути накладено штраф на хост, який знищує обсяг оперативної пам’яті, щоб зменшити обсяг оперативної пам’яті, щоб інші не страждали від перевантажена хост-машина.


-1

Деякий час Linux займає зовнішній віртуальний простір. Це розділ swap. Коли Ram заповнено, Linux займає цю область свопу для запуску процесу з низьким пріоритетом.


1
Жоден процес не запускається із свопу. Віртуальна пам'ять поділяється на однакові за розміром окремі одиниці, що називаються сторінками. При звільненні фізичної пам'яті сторінки з низькою пріоритетністю вилучаються з оперативної пам'яті. Хоча сторінки в кеш-файлі мають резервну копію файлової системи, анонімні сторінки повинні зберігатися в свопі. Пріоритет сторінки безпосередньо не пов'язаний з пріоритетом процесу, до якого він належить, але як часто він використовується. Якщо виконується процес намагається отримати доступ до сторінки не в фізичної пам'яті, помилка сторінки генеруються і процес витісняються на користь іншого процесу , а потрібна сторінка (и) вибирається з диска.
Томас Найман
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.