Функция vmalloc()

We use cookies. Read the Privacy and Cookie Policy

Функция vmalloc()

Функция vmalloc() работает аналогично функции kmalloc(), за исключением того, что она выделяет страницы памяти, которые только виртуально смежные и необязательно смежные физически. Точно так же работают и функции выделения памяти в пространстве пользователя: страницы памяти, которые выделяются с помощью функции malloc(), являются смежными в виртуальном адресном пространстве процесса, но нет никакой гарантии, что они смежные в физической оперативной памяти. Функция kmalloc() отличается тем, что гарантирует, что страницы памяти будут физически (и виртуально) смежными. Функция vmalloc() гарантирует только, что страницы будут смежными в виртуальном адресном пространстве ядра. Это реализуется путем выделения потенциально несмежных участков физической памяти и "исправления" таблиц страниц, чтобы отобразить эту физическую память в непрерывный участок логического адресного пространства.

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

Несмотря на то что физически смежные страницы памяти необходимы только в определенных случаях, большая часть кода ядра использует для выделения памяти функцию kmalloc(), а не vmalloc(). Это, в основном, делается из соображений производительности. Для того чтобы физически несмежные страницы памяти сделать смежными в виртуальном адресном пространстве, функция vmalloc() должна соответствующим образом заполнить таблицы страниц. Хуже того, страницы памяти, которые получаются с помощью функции vmalloc(), должны отображаться посредством страниц памяти, которые принадлежат к таблицам страниц (потому что выделяемые страницы памяти физически несмежные). Это приводит к значительно менее эффективному использованию буфера TLB[64], чем в случае, когда страницы памяти отображаются напрямую. Исходя из этих соображений функция vmalloc() используется только тогда, когда она абсолютно необходима, обычно это делается для выделения очень больших областей памяти. Например, при динамической загрузке модулей ядра, модули загружаются в память, которая выделяется с помощью функции vmalloc().

Функция vmalloc() объявлена в файле <linux/vmalloc.h> и определена в файле mm/vmalloc.с. Использование этой функции аналогично функции malloc() пространства пользователя.

void *vmalloc(unsigned long size);

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

Для освобождения памяти, выделенной с помощью функции vmalloc(), необходимо использовать функцию

void vfree(void *addr);

Эта функция освобождает участок памяти, который начинается с адреса addr и был ранее выделен с помощью функции vmalloc(). Данная функция также может переводить процесс в состояние ожидания и поэтому не может вызываться из контекста прерывания. Функция не возвращает никаких значений.

Использовать рассмотренные функции очень просто. Например, следующим образом.

char *buf;

buf = vmalloc(16 * PAGE_SIZE); /* получить 16 страниц памяти */

if (!buf)

 /* ошибка! Не удалось выделить память */

/*

* переменная buf теперь указывает на область памяти

* размером, по крайней мере, 16*PAGE_SIZE байт, которая состоит

* из виртуально смежных блоков памяти

*/

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

vfree(buf);