mmap: отображение в пользовательском пространстве буфера ядра, выделенного с помощью kmalloc - PullRequest
11 голосов
/ 06 августа 2011

Как правильно отобразить в пользовательском пространстве буфер, выделенный с помощью 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).Все работает, но я думаю, что в этом коде что-то не так:

  1. kmalloc может вернуть указатель, который не выровнен по странице, и, в этом случае, я не думаю, чтоисправить значение третьего параметра remap_pfn_range на самом деле в пространстве пользователя я прочитал неправильное значение.Вместо этого все работает, если я использую __get_free_page (потому что функция всегда возвращает указатель, который выровнен по странице) или когда kmalloc возвращает указатель, выровненный по странице.Отображение памяти работает с областями памяти, кратными PAGE_SIZE, поэтому следует ли выделять целую страницу вместо использования kmalloc?

  2. Когда вызывается my_mmap, ядро ​​имеетвыделил еще несколько страниц?Я спрашиваю об этом, потому что я нашел несколько реализаций пользовательского mmap метода, который вызывает remap_pfn_range с vma->vm_pgoff в качестве третьего параметра ... как это может быть полезно?Это кадр страницы первой новой выделенной страницы?Если в качестве третьего параметра я передаю фрейм страницы, как в my_mmap, я должен освободить страницы, начиная со страницы в vma->vm_pgoff?

  3. Однако я нашел реализацию 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, отображение будет работать хорошоПочему?

Спасибо всем!

1 Ответ

6 голосов
/ 11 августа 2011
  1. Да, вам следует выделить целое количество страниц.

  2. Нет, ядро ​​не выделило ни одной страницы. vm->vm_pgoff - запрошенное смещение в отображаемом устройстве - это последний параметр вызова mmap() пространства пользователя, переведенный из байтов в страницы. Вы, вероятно, смотрите на реализации mem или kmem mmap, и в этом случае смещение представляет физическую или линейную страницу, которую пользовательское пространство хочет отобразить.

  3. Это просто выделение буфера с выравниванием страницы в выделенном буфере kmalloc(). Вам лучше использовать __get_free_pages(), как вы уже догадались, вырезая посредника.

Вы должны проверить, что отображаемый размер не превышает ваш буфер.

...