У четвертому виданні популярного керівництва дані основи програмування в операційній системі 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, присвяченій налагодженню і оптимізації, ми обговоримо деякі засоби, які можуть допомогти вам виявити проблеми, пов'язані з пам'яттю.