2015-12-29 21 views
5

Hiện tại, tôi đang sử dụng một số example driver để tìm hiểu và từ đó tôi có trình điều khiển tùy chỉnh của riêng mình xung quanh. Mã mmap gần như giống hệt nhau, tiết kiệm cho thực tế là tôi cho phép người dùng quản lý kích thước yêu cầu của riêng họ và cấp phát bộ nhớ của tôi xung quanh đó và thực tế là tôi tự động tạo thiết bị char trong/dev.Sự khác biệt giữa dma_mmap_coherent và remap_pfn_range là gì?

Để giải thích ngữ cảnh, đối với trường hợp sử dụng của tôi, tôi muốn thu hẹp một vấn đề mà tôi đang gặp phải. dma_mmap_coherent testably hoạt động khi sử dụng bộ nhớ kmalloc'd, nhưng khi tôi có một vùng địa chỉ vật lý dự trữ mà tôi muốn sử dụng remap_pfn_range với nó lặng lẽ xuất hiện để làm việc, và dmesg không báo cáo bất kỳ lỗi nào, nhưng khi tôi đọc, không có vấn đề những gì tôi đã viết ở đó nó luôn trả về 0xff byte. Điều này đúng cho dù tôi sử dụng iowrite & ioread trong hạt nhân sau khi ioremap'ing bộ nhớ hoặc cố gắng để viết trong userland bằng cách sử dụng một thử nghiệm mmap'ing userland nhỏ.

Tôi đã thực hiện nhiều nghiên cứu về chủ đề này như tôi có thể nghĩ. Tất cả những gì tôi có thể tìm thấy cho tài liệu của remap_pfn_range là kernel.org page và một số lưu trữ danh sách gửi thư gmain hạt nhân trên remap_pfn_range thay thế remap_page_range. Đối với dma_mmap_coherent, tôi có thể tìm thêm một chút, including a presentation from the linux archives.

Cuối cùng phải có sự khác biệt; dường như có rất nhiều cách khác nhau để ánh xạ bộ nhớ hạt nhân vào vùng đất của người dùng. Câu hỏi cụ thể tôi có là: sự khác biệt giữa dma_mmap_coherentremap_pfn_range là gì?

Chỉnh sửa có thể là tốt đẹp để cung cấp tổng quan chung về cách ánh xạ bộ nhớ hạt nhân vào vùng người dùng nói chung, bao quát cách sử dụng apis khác nhau trong trình quay số mmap trình điều khiển hạt nhân.

+0

Bạn đã bao giờ tìm ra điều này, tức là sử dụng mmap và dma_mmap_coherent cùng nhau? Tôi không thể làm điều đó và tôi đã thực hiện các chức năng đọc và ghi của riêng mình. – user1876942

+0

Vâng, tôi đã sử dụng những chức năng cụ thể đó. Bạn có muốn một ví dụ? Tôi đã tìm kiếm sự khác biệt giữa remap_pfn_range và dma_mmap_coherent đặc biệt để tôi có thể biết được tuyến đường nào đi xuống. –

+0

Nếu bạn có thể đăng một ví dụ về tác phẩm này, điều đó thật tuyệt vời. Tôi đoán rằng mã phía người dùng là tiêu chuẩn và kmod là nơi tôi đang đi sai. – user1876942

Trả lời

0

dma_mmap_coherent() được xác định trong dma-mapping.h làm trình bao bọc xung quanh dma_mmap_attrs(). dma_mmap_attrs() cố gắng xem một tập hợp các dma_mmap_ops có là liên kết với thiết bị (struct device * dev) mà bạn đang hoạt động hay không, nếu nó không gọi dma_common_mmap() mà cuối cùng dẫn đến một cuộc gọi đến remap_pfn_range(), sau khi thiết lập trang bảo vệ như không thể lưu trữ được (xem dma_common_mmap() trong dma-mapping.c).

Đối với một cái nhìn tổng quan chung của mmap'ing bộ nhớ hạt nhân để công trình không gian của người dùng, sau đây là cách nhanh chóng và đơn giản của anh mmap'ing đệm DMA từ người sử dụng không gian:

  1. Cấp phát một vùng đệm thông qua một IOCTL và chỉ định một ID đệm cho mỗi đệm với một số lá cờ:

    /* A copy-from-user call needs to be done before in the IOCTL */ 
    static int my_ioctl_alloc(struct my_struct *info, struct alloc_info *alloc) 
    { 
    
         ... 
         info->buf->kvaddr = dma_alloc_coherent(dev, alloc->size, info->buf->phyaddr, GFP_KERNEL); 
         info->buf->buf_id = alloc->buf_id; 
         ... 
    } 
    
  2. Xác định một file mmap ops:

    static const struct file_operations my_fops = { 
         .open = my_open, 
         .close = my_close, 
         .mmap = my_mmap, 
         .unlocked_ioctl = my_ioctl, 
    }; 
    

    Đừng quên đăng ký cấu trúc my_fops ở đâu đó trong chức năng thăm dò của trình điều khiển của bạn.

  3. Thực hiện mmap tập tin ops:

    static int my_mmap(struct file *fptr, struct vm_area_struct *vma) 
    { 
         ... 
         desc_id = vma->vm_pgoff; 
         buf = find_buf_by_id(alloc, desc_id); 
         vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); 
         ret = remap_pfn_range(vma, vma->vm_start, buf->phyaddr >> PAGE_SHIFT, vma->vm_end - vma->vm_start, vma->vm_page_prot); 
         if (ret) { 
           /* Error Handle */ 
         } 
         return 0; 
    } 
    

Với trình điều khiển này kernel của bạn nên có tối thiểu để phân bổ và bộ đệm mmap. Giải phóng bộ đệm là một bài tập cho các điểm thưởng!

Trong ứng dụng, bạn sẽ mở() tệp và nhận tệp mô tả tệp hợp lệ fd, gọi cấp IOCTL và đặt ID bộ đệm trước khi thực hiện sao chép thành hạt nhân. Trong mmap, bạn sẽ cung cấp ID đệm thông qua các tham số offset:

 mmap(NULL, buf_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, buffer_id << PAGE_SHIFT); 

PAGE_SHIFT là một kiến ​​trúc phụ thuộc thời gian biên dịch MACRO cố định trong hạt nhân. Hy vọng điều này sẽ hữu ích.

Đây không phải là mã tuân thủ checkpatch.pl, cũng không phải là phương pháp hay nhất, nhưng đó là một cách tôi biết cách thực hiện việc này. Nhận xét/cải tiến/đề xuất chào mừng!

Xem Trình điều khiển thiết bị Linux - Chương 15: Lập bản đồ bộ nhớ và DMA cho các ví dụ sách giáo khoa và thông tin cơ bản tốt cho người đọc quan tâm.

Các vấn đề liên quan