Данная программа запрашивает с помощью библиотечного вызова malloc
указатель на один мегабайт памяти. Вы проверяете, успешно ли завершился вызов malloc
, и используете часть памяти, чтобы продемонстрировать ее наличие. Когда вы выполните программу, то увидите вывод фразы "Hello World", показывающий, что malloc
действительно вернул мегабайт используемой памяти. Мы не проверяем наличие мегабайта целиком; мы приняли на веру программный код malloc
!
Поскольку функция malloc
возвращает указатель типа void*
, вы преобразуете результат в нужный вам указатель типа char*
. Эта функция возвращает память, выровненную так, что она может быть преобразована в указатель любого типа.
Простое основание — современные системы Linux применяют 32-разрядные целые и 32-разрядные указатели, что позволяет задавать до 4 Гбайт. Эта способность задавать адреса с помощью 32-разрядного указателя без необходимости применения регистров сегментов или других приемов, называется
Выделение огромных объемов памяти
Теперь, когда вы увидели, что ОС Linux преодолевает ограничения модели памяти ОС MS-DOS, давайте усложним ей задачу. Приведенная в упражнении 7.2 программа запрашивает выделение объема памяти, большего, чем физически есть в машине, поэтому можно предположить, что функция malloc начнет давать сбои при приближении к максимальному объему физической памяти, поскольку ядру и всем остальным выполняющимся процессам также нужна память.
С помощью программы memory2.с мы собираемся запросить больше памяти, чем физически есть в машине. Вам нужно откорректировать определение PHY_MEM_MEGS
в соответствии с физическими ресурсами вашего компьютера.
#include
#include
#include
#define A_MEGABYTE (1024 * 1024)
#define PHY_MEM_MEGS 1024 /* Откорректируйте это число
должным образом */
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 %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 Кбайт и записывать данные в каждый полученный нами блок.
Далее приведена программа memory3.c. По своей истинной природе она крайне недружественная по отношению к пользователю и может очень серьезно повлиять на многопользовательскую машину. Если вас беспокоит подобный риск, лучше совсем не запускать ее; если вы окажитесь от выполнения этой программы, усвоению материала это не повредит.
#include
#include
#include