¿Cuál es la forma correcta de asignar en un espacio de usuario un búfer asignado con kmalloc? Quizás aún no entendía el mapeo de la memoria ... Escribí un módulo kernel que asigna este búfer (por ejemplo, 120 bytes) y lo leía y escribía en un proceso de espacio de usuario. Obviamente, creé un dispositivo char e implementé un método mmap
en la estructura file_operations
. Mi método es:mmap: asignación en el espacio de usuario un búfer de núcleo asignado con kmalloc
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;
}
donde mem_area
puntos en un área de memoria asignada con kmalloc
al inicio del módulo. El área se llena con el mismo valor (por ejemplo 0x10). Todas las obras pero creo que hay algo mal en este código:
kmalloc
podría devolver un puntero que no está alineado página y, en ese caso, no creo que es correcto el valor del tercer parámetro deremap_pfn_range
, de hecho, en el espacio de usuario, leí el valor incorrecto. En cambio, todo funciona si utilizo__get_free_page
(porque la función siempre devuelve un puntero que está alineado con la página) o cuandokmalloc
devuelve un puntero alineado con la página. El mapeo de memoria funciona con regiones de memoria que son múltiples dePAGE_SIZE
, entonces, ¿debo asignar una página completa en lugar de usarkmalloc
?Cuando
my_mmap
se denomina, el kernel ha asignado algunas páginas todavía? Pregunto esto porque encontré algunas implementaciones del método personalizadommap
que llama aremap_pfn_range
convma->vm_pgoff
como tercer parámetro ... ¿cómo podría ser útil esto? ¿Es este el marco de página de la primera página nueva asignada? Si paso como tercer parámetro un marco de página como lo hago enmy_mmap
, debería liberar páginas comenzando desde la página envma->vm_pgoff
?Sin embargo, encontré una implementación del método
mmap
que mapea un buffer asignado conkmalloc
. Para asignar correctamente el búfer, se realiza una operación (que no entiendo por el momento) antes delremap_pfn_range
. Supongamos quemem
es el puntero devuelto porkmalloc
,mem_area
se inicializa de esta manera:mem_area=(int *)(((unsigned long)mem + PAGE_SIZE - 1) & PAGE_MASK);
Así mem_area
contiene el mismo valor de mem
sólo si mem
está página alineado lo contrario, se debe contener el puntero al principio de la página siguiente. Sin embargo, con esta operación, si paso como tercer parámetro de remap_pfn_range
, la asignación de valor __pa(mem_area) >> PAGE_SHIFT
funciona bien. ¿Por qué?
¡Gracias a todos!
Tengo una pregunta similar, pero con el uso de parámetro de arranque 'mmap': http://stackoverflow.com/q/12790382/143897? ¿Podría darnos algunos de sus hallazgos? Gracias. –
¿No necesita un manejador de errores de página aquí para vm_operations_struct.fault? –
Ejemplo ejecutable mínimo: https://stackoverflow.com/questions/10760479/how-to-mmap-a-linux-kernel-buffer-to-user-space/45645732#45645732 –