Выделение памяти в ядре Linux

Основной единицой управления памятью в ядре Linux является страница памяти. И хотя наименьшой адресуемой единицой памяти является байт, модуль управления памятью(MMU) работает только с страницами памяти.

 

В ядре существует низкоуровневые механизмы выделения страниц памяти.

 

#include <linux/gfp.h>
 
struct page * alloc_pages(gfp_t gfp_mask, unsigned int order);
 
struct page * alloc_page(gfp_t gfp_mask);
 
void * page_address(struct page *page);
 
unsigned long __get_free_pages(gfp_t gfp_mask, unsigned int order);
 
unsigned long __get_free_page(gfp_t gfp_mask);
 
unsigned long get_zeroed_page(unsigned int gfp_mask);

 

Первая функция возвращает указатель на на первую из 2 в степени order (1 << order)  смежных страниц памяти, в случае ошибки возвращается NULL. Всегда проверяйте результат выполнения этой(как и других) функции, ибо цена ошибки в ядре операционной системы велика. Переменная gfp_t gfp_mask содержит битовую маску параметров. В этой переменной хранятся модификаторы зон, модификаторы операций и модификаторы и флаги типов, больше можно прочитать в в файле gfp.h. Опишу лишь некоторое из составных модификаторов(флаги типов), применяемых чаще всего:

 

 #define GFP_NOWAIT
 #define GFP_ATOMIC               /* Применяется в основном в IRQ */
 #define GFP_NOIO
 #define GFP_NOFS
 #define GFP_KERNEL               /* Обычный режим выделения памяти в ядре */
 #define GFP_TEMPORARY
 #define GFP_USER
 #define GFP_HIGHUSER
 #define GFP_HIGHUSER_MOVABLE

 

Функция alloc_page выделяет одну страницу памяти. Для того что бы преобразовать struct page к адресу который можно использовать для записи и чтения стандартными для С способами
используется функция page_address.

Функция __get_free_pages так же как alloc_pages выделяет 2 в степени order страниц памяти, только она возвращает не указатель на struct page, а адрес в виртуальной памяти. Это все
равно что вызвать сначала alloc_pages, а потом page_address__get_free_pageделает тоже самое но с 1-ой страницой памяти, а вызов get_zeroed_page еще и обнуляет эту страницу.

Для освобождения выделенных страниц памяти нужно использовать функции:

 

void __free_pages(struct page *page, unsigned int order);
 
void free_pages(unsigned long addr, unsigned int order);
 
void free_page(unsigned long addr);

 

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

 

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

dreamway89

dreamway89 wrote 29 posts

Post navigation


Добавить комментарий

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes:

<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>