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