Как правильно отобразить в процессе пользовательского пространства буфер, выделенный с помощью 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
является правильным, на самом деле в пользовательском пространстве я прочитал неправильное значение. d все работает, если я использую __ 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
работает хорошо. Почему?
Всем спасибо!