Получение больших буферов

Предыдущая  Содержание  Следующая V*D*V

Как мы уже отмечали в предыдущих разделах, выделение больших непрерывных буферов памяти может привести к неудачам. Системная память фрагментируется с течением времени и есть вероятность, что действительно большая область памяти просто не будет доступна. Поскольку, как правило, есть способы выполнения работы без огромных буферов, разработчики ядра не дают высокого приоритета для выполнения работы большого выделения памяти. Прежде чем пытаться получить большую область памяти, вам следует всерьёз задуматься об альтернативах. Самым лучшим способом выполнения больших операций ввода/вывода являются операции разборки/сборки, которые мы обсуждаем в разделе "Преобразования разборки/сборки" в Главе 15.

Получение выделенного буфера во время загрузки

Если вам действительно необходим огромный буфер физически непрерывной памяти, часто лучший подход - выделить запрашиваемую память во время загрузки. Выделение памяти во время загрузки является только способом получить последовательные страницы памяти в обход ограничений, вводимых __get_free_pages на размер буфера, как с точки зрения максимально допустимого размера, так и ограниченного выбора размеров. Выделение памяти при загрузке является "грязной" техникой, потому что она обходит все политики управления памятью, резервируя частный пул памяти. Эта техника является негибкой и безвкусной, но она также наименее подвержена неудаче. Нет необходимости говорить, что модуль не может выделять память во время загрузки; только драйверы, непосредственно связанные с ядром, могут сделать это.

 

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

 

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

 

Выделение памяти во время загрузки выполняется вызовом одной из следующих функций:

 

#include <linux/bootmem.h>

void *alloc_bootmem(unsigned long size);

void *alloc_bootmem_low(unsigned long size);

void *alloc_bootmem_pages(unsigned long size);

void *alloc_bootmem_low_pages(unsigned long size);

 

Эти функции выделяют либо целые страницы (если они заканчиваются _pages) или не странично-выровненные области памяти. Выделенная память может быть верхней областью памяти, если не используется одна из _low версий. При выделении этого буфера для драйвера устройства, вы, вероятно, захотите использовать его для операций DMA, а это не всегда возможно с верхней областью памяти; таким образом, вы, вероятно, захотите использовать один из _low вариантов.

 

Освобождение памяти, выделенной при загрузке, редко; вы почти наверняка будете не в состоянии получить её позже, если этого захотите. Однако, существует интерфейс для освобождения этой память:

 

void free_bootmem(unsigned long addr, unsigned long size);

 

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

 

Если вы должны использовать выделение памяти во время загрузки, необходимо связать свой драйвер непосредственно с ядром. Просмотрите файлы в исходных текстах ядра в Documentation/kbuild для получения дополнительной информации о том, как это должно быть сделано.

Предыдущая  Содержание  Следующая