2011-08-06 88 views
10

哪一個正確的方式在用戶空間進程中映射一個用kmalloc分配的緩衝區?也許我不明白內存映射呢......我寫了一個內核模塊來分配這個緩衝區(例如120字節),我會在用戶空間進程中讀寫它。顯然,我創建了一個char設備,並在file_operations結構中實現了mmap方法。我的方法是:mmap:在用戶空間映射一個用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; 
} 

其中mem_area點在存儲器領域模塊初始化與kmalloc分配。該區域填充相同的值(例如0x10)。所有的作品,但我覺得有什麼不對在此代碼:

  1. kmalloc可以返回未對齊頁的指針,在這種情況下,我不認爲這是正確的第三個參數的值remap_pfn_range其實在用戶空間我讀錯誤的值。如果我使用__get_free_page(因爲該函數總是返回一個頁面對齊的指針),或者當kmalloc返回一個頁面對齊的指針,所有工作。內存映射適用於多個PAGE_SIZE的內存區域,因此,我應該分配整個頁面而不是使用kmalloc

  2. 當調用my_mmap時,內核已經分配了一些頁面呢?我問這個,因爲我發現一些自定義mmap方法的實現,調用remap_pfn_rangevma->vm_pgoff作爲第三個參數......這可能有用嗎?這是第一個新分配頁面的頁框嗎?如果我作爲第三個參數傳遞頁面框架,就像我在my_mmap中做的那樣,我應該從vma->vm_pgoff頁面開始免費頁面?

  3. 但是,我發現一個mmap方法的實現映射了一個緩衝區分配kmalloc。爲了正確映射緩衝區,在remap_pfn_range之前執行一個操作(我現在不打算)。假設memkmalloc返回的指針,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映射效果良好。爲什麼?

謝謝大家!

+0

我有一個類似的問題,但使用啓動參數'mmap':http://stackoverflow.com/q/12790382/143897?你能提供一些你的發現嗎?謝謝。 –

+0

您不需要爲vm_operations_struct.fault設置頁面錯誤處理程序嗎? –

+0

最小的可運行示例:https://stackoverflow.com/questions/10760479/how-to-mmap-a-linux-kernel-buffer-to-user-space/45645732#45645732 –

回答

6
  1. 是的,你應該分配一整頁的頁面。

  2. 不,內核沒有分配任何頁面。 vm->vm_pgoff是被映射設備內的請求偏移量 - 它是用戶空間mmap()調用的最後一個參數,從字節翻譯爲頁面。您可能正在查看memkmem mmap實現,在這種情況下,偏移量表示用戶空間想要映射的物理或線性頁面。

  3. 這就是在kmalloc()分配的緩衝區內分配一個頁面對齊的緩衝區。正如你已經猜測的那樣,你最好使用__get_free_pages(),切斷中間人。

您應該測試被映射的大小不超過您的緩衝區。

+0

謝謝caf for the anwser!我仍然不明白第二點...我沒有看'mem'或'kmem'的實現,但是我在Linux設備驅動程序書中發現它...現在我知道'vma-> vm_pgoff'是在映射的設備中有偏移,但是如果我將'remap_pfn_range'作爲第三個參數'vma-> vm_pgoff'傳遞給我映射的設備中的內存? – MirkoBanchi

+0

@caf我有一個類似的問題,但使用啓動參數mmap:stackoverflow.com/q/12790382/143897?你能提供一些你的發現嗎?謝謝。 –

相關問題