Чтение онлайн

на главную - закладки

Жанры

Основы программирования в Linux
Шрифт:

printf("%s — now allocated %d Megabytes\n", 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

Как это работает

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

PHY_MEM_MEGS
объем памяти, имеющейся у вашего компьютера. Удивительно, что эта программа вообще работает, потому что мы, как оказалось, создали программу, которая использует каждый байт физической памяти на машине одного из авторов. Обратите внимание на то, что в нашем вызове
malloc
применяется тип
size_t
.

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

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

Упражнение 7.3. Доступная память

Далее приведена программа memory3.c. По своей истинной природе она крайне недружественная по отношению к пользователю и может очень серьезно повлиять на многопользовательскую машину. Если вас беспокоит подобный риск, лучше совсем не запускать ее; если вы окажитесь от выполнения этой программы, усвоению материала это не повредит.

#include <unistd.h>

#include <stdlib.h>

#include <stdio.h>

#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 %d Megabytes\n", 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

После этого программа завершается. Она выполняется несколько секунд и существенно замедляется при приближении к размеру, равному объему физической памяти на компьютере, а также активно использует жесткий диск. Тем не менее программа выделяла и получала доступ к области памяти, большей по размеру объема физической памяти, которая была установлена на машине одного из авторов во время написания этой главы. В конце концов, система защищает себя от этой довольно агрессивной программы и уничтожает ее. В некоторых системах она может тихо закончить выполнение, когда функция

malloc
завершается аварийно.

Как это работает

Память, выделяемая приложению, управляется ядром системы Linux. Каждый раз, когда программа запрашивает память, пытается записывать в память или считывать из памяти, которая была выделена, ядро Linux решает, как обрабатывать этот запрос.

Сначала ядро может использовать свободную физическую память для удовлетворения запроса приложения на выделение памяти, но когда физическая память исчерпана, ядро начинает использовать так называемую область свопинга или подкачки. В ОС Linux это отдельная область диска, выделяемая во время инсталляции системы. Если вы знакомы с ОС Windows, функционирование области свопинга в Linux немного напоминает файл подкачки в Windows. Но в отличие от ОС Windows при написании программного кода не нужно беспокоиться ни о локальной, ни о глобальной динамической памяти (heap), ни о выгружаемых сегментах памяти — ядро Linux все организует для вас.

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

Говоря более профессиональным языком, система Linux реализует систему виртуальной памяти с подкачкой страниц по требованию. Вся память, видимая программами пользователя, — виртуальная, т. е. реально не существующая в физическом адресном пространстве, используемом программой. Система Linux делит всю память на страницы, обычно размером 4096 байтов. Когда программа пытается обратиться к памяти, выполняется преобразование виртуальной памяти в физическую, конкретный способ реализации которого и затрачиваемое на преобразование время зависят от конкретного оборудования, применяемого вами. Когда выполняется обращение к области памяти, физически нерезидентной, возникает ошибка страницы памяти и управление передается ядру.

Ядро Linux проверяет адрес, к которому обратилась программа, и, если это допустимый для нее адрес, определяет, какую страницу физической памяти сделать доступной. Затем оно либо выделяет память для страницы, если она еще не записывалась ни разу, либо, если страница хранится на диске в области свопинга, считывает страницу памяти, содержащую данные, в физическую память (возможно выгружая на диск имеющуюся в памяти страницу). Затем после преобразования адресов виртуальной памяти в соответствующие физические адреса ядро разрешает пользовательской программе продолжить выполнение. Приложениям в ОС Linux не нужно заботиться об этих действиях, поскольку их реализация полностью скрыта в ядре.

Поделиться:
Популярные книги

Большая книга о новой жизни, которую никогда не поздно начать (сборник)

Норбеков Мирзакарим Санакулович
Дом и Семья:
здоровье и красота
5.00
рейтинг книги
Большая книга о новой жизни, которую никогда не поздно начать (сборник)

Моров. Том 1 и Том 2

Кощеев Владимир
1. Моров
Фантастика:
попаданцы
альтернативная история
аниме
5.00
рейтинг книги
Моров. Том 1 и Том 2

Сильнейший ученик. Том 2

Ткачев Андрей Юрьевич
2. Пробуждение крови
Фантастика:
фэнтези
попаданцы
аниме
5.00
рейтинг книги
Сильнейший ученик. Том 2

Чужак из ниоткуда 2

Евтушенко Алексей Анатольевич
2. Чужак из ниоткуда
Фантастика:
попаданцы
альтернативная история
5.00
рейтинг книги
Чужак из ниоткуда 2

Гром Раскатного. Том 2

Володин Григорий Григорьевич
2. Штормовой Предел
Фантастика:
боевая фантастика
попаданцы
аниме
5.00
рейтинг книги
Гром Раскатного. Том 2

На границе империй. Том 10. Часть 5

INDIGO
23. Фортуна дама переменчивая
Фантастика:
космическая фантастика
попаданцы
5.00
рейтинг книги
На границе империй. Том 10. Часть 5

Бастард Императора. Том 11

Орлов Андрей Юрьевич
11. Бастард Императора
Фантастика:
городское фэнтези
попаданцы
аниме
фэнтези
5.00
рейтинг книги
Бастард Императора. Том 11

Газлайтер. Том 14

Володин Григорий Григорьевич
14. История Телепата
Фантастика:
попаданцы
аниме
фэнтези
5.00
рейтинг книги
Газлайтер. Том 14

Украсть у президента

Гриньков Владимир Васильевич
Детективы:
триллеры
5.00
рейтинг книги
Украсть у президента

Простолюдин

Рокотов Алексей
1. Путь князя
Фантастика:
боевая фантастика
рпг
5.00
рейтинг книги
Простолюдин

Я до сих пор князь. Книга XXII

Дрейк Сириус
22. Дорогой барон!
Фантастика:
юмористическое фэнтези
аниме
попаданцы
5.00
рейтинг книги
Я до сих пор князь. Книга XXII

Перешагнуть пропасть

Муравьёв Константин Николаевич
1. Перешагнуть пропасть
Фантастика:
боевая фантастика
космическая фантастика
8.38
рейтинг книги
Перешагнуть пропасть

Убивать чтобы жить 2

Бор Жорж
2. УЧЖ
Фантастика:
героическая фантастика
боевая фантастика
рпг
5.00
рейтинг книги
Убивать чтобы жить 2

Артефактор. Возвращение блудного императора

Седых Александр Иванович
2. Артефактор
Фантастика:
фэнтези
боевая фантастика
4.33
рейтинг книги
Артефактор. Возвращение блудного императора