Рейтинговые книги
Читем онлайн Разработка ядра Linux - Роберт Лав

Шрифт:

-
+

Интервал:

-
+

Закладка:

Сделать
1 ... 93 94 95 96 97 98 99 100 101 ... 132

Функция find_vma_prev()

Функция find_vma_prev() работает аналогично функции find_vma(), но дополнительно она еще возвращает последнюю область VMA, которая заканчивается перед адресом addr. Эта функция также определена в файле mma/mmap.c и объявлена в файле <linux/ram.h> следующим образом.

struct vm_area_struct* find vma_prev(struct mm_struct *mm,

 unsigned long addr, struct vm_area_struct **pprev);

Параметр pprev после возвращения из функции содержит указатель на предыдущую область VMA.

Функция find_vma_intersection()

Функция find_vma_intersection() возвращает первую область памяти, которая перекрывается с указанным интервалом адресов. Эта функция определена в файле <linux/mm.h> следующим образом. Это функция с подстановкой тела.

static inline struct vm_area_struct* find_vma_intersection(

 struct mm_struct *mm, unsigned long start_addr,

 unsigned long end_addr) {

 struct vm_area_struct *vma;

 vma = find_vma(mm, start_addr);

 if (vma && end_addr <= vma->vm_start)

  vma = NULL;

 return vma;

}

Первый параметр — адресное пространство, в котором выполняется поиск, параметр start_addr — это первый адрес интервала адресов, а параметр end_addr — последний адрес интервала.

Очевидно, что если функция find_vma() возвращает значение NULL, то это же значение будет возвращать и функция find_vma_intersection(). Если функция find_vma() возвращает существующую область VMA, то функция find_vma_intersection() возвратит ту же область только тогда, когда эта область не начинается после конца данного диапазона адресов. Если область памяти, которая возвращается функцией find_vma(), начинается после последнего адреса из указанного диапазона, то функция find_vma_intersection() возвращает значение NULL.

Функции mmap() и do_mmap(): создание интервала адресов

Функция do_mmap() используется ядром для создания нового линейного интервала адресов. Говорить, что эта функция создает новую область VMA, — технически не корректно, поскольку если создаваемый интервал адресов является смежным с существующим интервалом адресов и у этих интервалов одинаковые права доступа, то два интервала объединяются в один. Если это невозможно, то создается новая область VMA В любом случае функция do_mmap() — это функция, которая добавляет интервал адресов к адресному пространству процесса, независимо от того, создается ли при этом новая область VMA или расширяется существующая.

Функция do_mmap() объявлена в файле <linux/mm.h> следующим образом.

unsigned long do_mmap(struct file *file,

 unsigned long addr, unsigned long len,

 unsigned long prot, unsigned long flag,

 unsigned long offset);

Эта функция выполняет отображение на память содержимого файла file начиная с позиции в файле offset; размер отображаемого участка равен len байт. Значения параметров file и offset могут быть нулевыми, в этом случае отображение не будет резервироваться (сохраняться) в файле. Такое отображение называется анонимным (anonymous mapping). Если указан файл и смещение, то отображение называется отображением файла в память (file-backed mapping).

Параметр addr указывает (точнее, всего лишь подсказывает), откуда начинать поиск свободного интервала адресов.

Параметр prot указывает права доступа для страниц памяти в данной области. Возможные значение флагов зависят от аппаратной платформы и описаны в файле <asm/mman.h>. Хотя на практике для всех аппаратных платформ определены флаги, приведенные в табл. 14.2.

Таблица 14.2. Флаги защиты страниц памяти

Флаг Влияние на страницы памяти в созданном интервале адресов PROT_READ Соответствует флагу VM_READ PROT_WRITE Соответствует флагу VM_WRITE PROT_EXEC Соответствует флагу VM_EXEC PROT_NONE К страницам памяти нет доступа

Параметр flags позволяет указать все остальные флаги области VMA Эти флаги также определены в <asm/mman.h> и приведены в табл. 14.3.

Таблица 14.3. Флаги защиты страниц памяти

Флаг Влияние на созданный интервал адресов MAP_SHARED Отображение может быть совместно используемым MAP_PRIVATE Отображение не может быть совместно используемым MAP_FIXED Создаваемый интервал адресов должен начинаться с указанного адреса addr MAP_ANONYMOUS Отображение является анонимным, а не отображением файла MAP_GROWSDOWN Соответствует флагу VM_GROWSDOWN MAP_DENYWRITE Соответствует флагу VM_DENYWRITE MAP_EXECUTABLE Соответствует флагу VM_EXECUTABLE MAP_LOCKED Соответствует флагу VM_LOCKED MAP_NORESERVE Нет необходимости резервировать память для отображения MAP_POPULATE Предварительно заполнить (prefault) таблицы страниц MAP_NONBLOCK Не блокировать при операциях ввода-вывода

Если какой-либо из параметров имеет недопустимое значение, то функция do_mmap() возвращает отрицательное число. В противном случае создастся необходимый интервал адресов. Если это возможно, то этот интервал объединяется с соседней областью памяти. Если это невозможно, то создается новая структура vm_area_struct, которая выделяется в слябовом кэше vm_area_cachep. После этого новая область памяти добавляется в связанный список и красно-черное дерево областей памяти адресного пространства с помощью функции vma_link(). Затем обновляется значение поля total_vm в дескрипторе памяти. В конце концов, функция возвращает начальный адрес вновь созданного интервала адресов.

Системный вызов mmap()

Возможности функции do_mmap() экспортируются в пространство пользователя с помощью системного вызова mmap(), который определен следующим образом.

void *mmap2(void *start,

 size_t length, int prot, int flags, int fd, off_t pgoff);

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

Функции munmap() и do_munmap(): удаление интервала адресов

Функция do_munmap() удаляет интервал адресов из указанного адресного пространства процесса. Эта функция объявлена в файле <asm/mman.h> следующим образом.

int do_munmap(struct mm_struct *mm,

 unsigned long start, size_t len);

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

Системный вызов munmap()

Системный вызов munmap() экспортируется в адресное пространство пользователя, чтобы иметь возможность удалять интервалы адресов из адресного пространства. Эта функция является комплиментарной к системному вызову mmap() и имеет следующий прототип.

int munmap(void*start, size_t length);

1 ... 93 94 95 96 97 98 99 100 101 ... 132
На этой странице вы можете бесплатно читать книгу Разработка ядра Linux - Роберт Лав бесплатно.
Похожие на Разработка ядра Linux - Роберт Лав книги

Оставить комментарий