10.4 Отображение файла / памяти — тонкости mmap() в uClinux

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

В Linux области памяти отображаются в адресное пространство процесса с помощью системного вызова mmap(). Отображённая область управляется с помощью флагов защиты, таких как PROT_READ и PROT_WRITE, а способ использования, закрытое (private) или разделяемое (shared) отображение, указывается с помощью флагов MAP_PRIVATE и MAP_SHARED. Например, загрузчик отображает текстовые области разделяемых библиотеки как только читаемые общие, разделяемые (PROT_READ и MAP_SHARED) области в пространстве процесса приложения.

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

В uClinux, без обработчика ошибки страницы, предоставляемые mmap функциональные возможности очень примитивны. Следующие две формы mmap не могут быть реализованы из-за отсутствия MMU. Мы кратко обсудим причины.

 

mmap(MAP_PRIVATE, PROT_WRITE) не реализована. Этот тип отображения создаёт отображение файла с разрешённой  записью в область виртуальных адресов процесса. Это означает, что страницы должны быть выделены в момент записи и удерживаются одним процессом, и этот процесс в одиночку видит изменения. Обработчик ошибки страницы заботится о выделении страниц когда и как только они записываются процессом и, таким образом, память выделяется только для тех страниц файла, которые изменены процессом.

mmap(MAP_SHARED, PROT_WRITE, file) не реализована. Стандартная реализация в Linux для этого типа вызова mmap создаёт общие страницы памяти для разных процессов и записи на диске в эту область будут синхронизированы. Страницы отображаются, как и ранее, срабатыванием ошибки страницы памяти после первой записи на страницу и помечаются как "грязные" (изменённые). Позже ядро запишет изменённые страницы на диск и пометит их готовыми к следующей обработке ошибки страницы в случае более поздней записи.

 

Оба приведённых выше варианта требуют работающего обработчика ошибок страницы, доступного только при аппаратном MMU. Следовательно, в uClinux это не может быть реализовано. В uClinux реализацией в ядре mmap является do_mmap_pgoff(). do_mmap_pgoff() для случаев без MMU выполняет следующие действия:

 

1.Проверяет наличие флагов защиты и отображения для случаев, которые не реализованы.
 
 …
if ((flags & MAP_SHARED) && (prot & PROT_WRITE) && (file)) {
 printk("MAP_SHARED not supported (cannot write mappings
        to disk)\n");
 return -EINVAL;
}
if ((prot & PROT_WRITE) && (flags & MAP_PRIVATE)) {
 printk("Private writable mappings not supported\n");
 return -EINVAL;
}
 …
 

2.Если предоставлен файловый указатель и если файловые операции этого файла поддерживаются функцией mmap, то вызывается соответствующая файлу mmap.
 
 …
if (file && file->f_ops->mmap)
 file->f_ops->mmap(file, &vma);
return vma.vm_start;
 …

 

3.Если указатель на файл не предоставлен, то выделяется запрашиваемая память из распределителя памяти ядра с помощью kmalloc.
 
 …
 …
result = kmalloc(len, GFP_KERNEL);
 …
 …

 

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