Виділення величезних обсягів пам'яті

Виділення величезних обсягів пам'яті

У четвертому виданні популярного керівництва дані основи програмування в операційній системі Linux. Розглянуто: використання бібліотек C / C ++ і стан-дротяні засобів розробки, організація системних викликів, файловий ввід / вивід, взаємодія процесів, програмування засобами командної оболонки, створення графічних користувацьких інтерфейсів за допомогою інструментальних засобів GTK + або Qt, застосування сокетів і ін. Описано компіляція програм, їх компоновка c бібліотеками та робота з термінальним вводом / виводом. Дано прийоми створення програмного забезпечення в середовищах GNOME® і KDE®, зберігання даних з використанням СУБД MySQL® і налагодження програм. Книга добре структурована, що робить навчання легким і швидким.

Для початківців Linux-програмістів

Книга: Основи програмування в Linux

Виділення величезних обсягів пам'яті

Розділи на цій сторінці:

Виділення величезних обсягів пам'яті

Тепер, коли ви побачили, що ОС Linux долає обмеження моделі пам'яті ОС MS-DOS, давайте усложним їй завдання. Наведена у вправі 7.2 програма запитує виділення обсягу пам'яті, більшого, ніж фізично є в машині, тому можна припустити, що функція malloc почне давати збої при наближенні до максимального обсягу фізичної пам'яті, оскільки ядра і всім іншим що виконуються процесам також потрібна пам'ять.

Вправа 7.2. Запит на всю фізичну пам'ять

За допомогою програми memory2.с ми збираємося запросити більше пам'яті, ніж фізично є в машині. Вам потрібно відкоригувати визначення PHY_MEM_MEGS відповідно до фізичними ресурсами вашого комп'ютера.

#include
#include
#include
#define A_MEGABYTE (1024 * 1024)
#define PHY_MEM_MEGS тисячу двадцять чотири / * Відкоректуйте це число
належним чином */
int main () char * some_memory;
size_t size_to_allocate = A_MEGABYTE;
int megs_obtained = 0;
while (megs_obtained <(PHY_MEM_MEGS * 2)) some_memory = (char *)malloc(size_to_allocate);
if (some_memory! = NULL) megs_obtained ++;
sprintf (somememory, "Hello World");
printf ( "% s - now allocated. Megabytesn", some_memory, megs_obtained);
> Else exit (EXIT_FAILURE);
>
>
exit (EXIT_SUCCESS);
>

Далі наведено трохи скорочений висновок:

$ ./memory3
Hello World - now allocated 1 Megabytes
Hello World - now allocated 2 Megabytes
.
Hello World - now allocated 2047 Megabytes
Hello World - now allocated 2048 Megabytes

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

Продовжимо дослідження і подивимося, скільки пам'яті ми зможемо виділити на цій машині за допомогою програми memory3.c (вправа 7.3). Оскільки вже зрозуміло, що система Linux здатна дуже розумно обходитися з запитами пам'яті, ми кожен раз будемо виділяти пам'ять по 1 Кбайт і записувати дані в кожен отриманий нами блок.

Вправа 7.3. доступна пам'ять

Далі приведена програма memory3.c. За своєї істинної природи вона вкрай недружня по відношенню до користувача і може дуже серйозно вплинути на багато користувачів машину. Якщо вас турбує подібний ризик, краще зовсім не запускати її; якщо ви опинитеся від виконання цієї програми, засвоєнню матеріалу це не зашкодить.

#include
#include
#include
#define ONE_K (1024)
int main () char * some_memory;
int size_to_allocate = ONE_K;
int megs_obtained = 0;
int ks_obtained = 0;
while (1) for (ks_obtained = 0; ks_obtained <1024; ks_obtained++) some_memory = (char *)malloc(size_to_allocate);
if (some_memory == NULL) exit (EXIT_FAILURE);
sprintf (some_memory, "Hello World");
>
megs_obtained ++;
printf ( "Now allocated. Megabytesn", megs_obtained);
>
exit (EXIT_SUCCESS);
>

На цей раз висновок, також скорочений, виглядає наступним чином:

$ ./memory3
Now allocated 1 Megabytes
.
Now allocated +1535 Megabytes
Now allocated 1536 Megabytes
Out of Memory: Killed process 2365
Killed

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

Спочатку ядро ​​може використовувати вільну фізичну пам'ять для задоволення запиту додатки на виділення пам'яті, але коли фізична пам'ять вичерпана, ядро ​​починає використовувати так звану область свопінгу або підкачки. В ОС Linux це окрема область диска, що виділяється під час інсталяції системи. Якщо ви знайомі з ОС Windows, функціонування галузі свопинга в Linux трохи нагадує файл підкачки в Windows. Але на відміну від ОС Windows при написанні програмного коду не потрібно турбуватися ні про локальну, ні про глобальну динамічної пам'яті (heap), ні про що вивантажуються сегментах пам'яті - ядро ​​Linux все організує для вас.

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

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

Примітка

Це поведінка, що супроводжується знищенням процесу, відрізняється від поведінки більш старих версій Linux і безлічі інших варіантів UNIX, в яких просто аварійно завершувалася функція malloc. Називається воно знищенням через брак пам'яті (out of memory (OOM) killer), і хоча може здатися надто радикальним, насправді служить розумним компромісом між можливістю швидкого і ефективного виділення пам'яті процесам і необхідністю власного захисту ядра від повного вичерпання ресурсів, що є серйозною проблемою.

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

Звичайний результат - аварійне завершення наступних викликів malloc не через брак пам'яті, а через пошкодження структур пам'яті. Такі проблеми буває важко відстежити, і чим швидше в програмах виявиться помилка, тим більше шансів знайти причину. У розділі 10, присвяченій налагодженню і оптимізації, ми обговоримо деякі засоби, які можуть допомогти вам виявити проблеми, пов'язані з пам'яттю.

Схожі статті