Как правильно отобразить в пользовательском пространстве буфер, выделенный с помощью kmalloc?Возможно я еще не понимал отображение памяти ... Я пишу модуль ядра, который выделяет этот буфер (например, 120 байт), и я бы читал и записывал его в процессе пользовательского пространства.Очевидно, я создал char-устройство и реализовал метод mmap
в структуре file_operations
.Мой метод:
static int my_mmap(struct file *filp, struct vm_area_struct *vma)
{
//printk(KERN_INFO "Allocated virtual memory length = %d", vma->vm_end - vma->vm_start);
long unsigned int size = vma->vm_end - vma->vm_start;
if (remap_pfn_range(vma, vma->vm_start,
__pa(mem_area) >> PAGE_SHIFT, //what about vma->vm_pgoff?
size,
vma->vm_page_prot) < 0)
return -EAGAIN;
vma->vm_flags |= VM_LOCKED;
vma->vm_ops = &vmops;
vma->vm_flags |= VM_RESERVED;
my_vm_open(vma);
return 0;
}
, где mem_area
указывает на область памяти, выделенную с помощью kmalloc
в модуле init.Область заполняется тем же значением (например, 0x10).Все работает, но я думаю, что в этом коде что-то не так:
kmalloc
может вернуть указатель, который не выровнен по странице, и, в этом случае, я не думаю, чтоисправить значение третьего параметра remap_pfn_range
на самом деле в пространстве пользователя я прочитал неправильное значение.Вместо этого все работает, если я использую __get_free_page
(потому что функция всегда возвращает указатель, который выровнен по странице) или когда kmalloc
возвращает указатель, выровненный по странице.Отображение памяти работает с областями памяти, кратными PAGE_SIZE
, поэтому следует ли выделять целую страницу вместо использования kmalloc
?
Когда вызывается my_mmap
, ядро имеетвыделил еще несколько страниц?Я спрашиваю об этом, потому что я нашел несколько реализаций пользовательского mmap
метода, который вызывает remap_pfn_range
с vma->vm_pgoff
в качестве третьего параметра ... как это может быть полезно?Это кадр страницы первой новой выделенной страницы?Если в качестве третьего параметра я передаю фрейм страницы, как в my_mmap
, я должен освободить страницы, начиная со страницы в vma->vm_pgoff
?
Однако я нашел реализацию mmap
метод, который отображает буфер, выделенный с kmalloc
.Чтобы правильно отобразить буфер, операция (которую я пока не понимаю) выполняется до remap_pfn_range
.Предположим, что mem
является указателем, возвращаемым kmalloc
, mem_area
инициализируется следующим образом:
mem_area=(int *)(((unsigned long)mem + PAGE_SIZE - 1) & PAGE_MASK);
Так что mem_area
содержит то же значение mem
только если mem
выровнена по страницам, в противном случае указатель должен содержать указатель в начале следующей страницы.Тем не менее, с этой операцией, если я передам в качестве третьего параметра remap_pfn_range
значение __pa(mem_area) >> PAGE_SHIFT
, отображение будет работать хорошоПочему?
Спасибо всем!