Time: PM
Location: dormitory ..
"Mr. Wang, I won't talk much today, but I didn't finish talking about it yesterday. Otherwise, I won't be able to even get up." I urged.
As mentioned in the previous section, if the memory applied for by kmalloc () is to be mapped to the user space, you can use mem_map_reserve () to set it to retained. How to operate it? Here is a template:
// Kernel module Loading Function Int _ Init kmalloc_map_init ( Void ) {../Apply for the device number and add the cedv struct buffer = kmalloc (buf_size, gfp_kernel ); // Apply for Buffer For (Page = pai_to_page (buffer); page <pai_to_page (buffer + buf_size); Page ++) {mem_map_reserve (PAGE ); // Property is retained }} // MMAP () function Static Int Kmalloc_map_mmap ( Struct File * filp, Struct Vm_area_struct * VMA ){ Unsigned Long Page, Pos; Unsigned Long Start = ( Unsigned Long ) VMA-> start; Unsigned Long Size = ( Unsigned Long ) (VMA-> end-VMA-> Start); printk (kern_info ,"Mmaptest_mmap called \ n "); If (Size> buf_size) // The region to be mapped is too large. Return -Einval; Pos = ( Unsigned Long ) Buffer; While (Size> 0) // Map all pages in the buffer {Page = maid (( Void *) POS ); If (Remap_page_range (START, page, page_size, page_sharred )) Return -Eagain; Start + = page_size; POS + = page_size; size-= page_size ;} Return 0 ;}
In addition, generally, the IO memory needs to be nocache when mapped. In this case, set the nocache flag for VMA-> vm_page_prot. As follows:
Static IntXxx_nocache_mmap (StructFile * filp,StructVm_area_struct * VMA) {VMA-> vm_page_prot = pgprot_noncached (VMA-> vm_page_prot );// Assign the nocache flagVMA-> vm_pgoff = (u32) map_start> page_shift );If(Rempa_pfn_range (VMA, VMA-> vm_start, VMA-> vm_pgoff, VMA-> vm_end-vm_start, VMA-> vm_page_prot ));Return-Eaggin;Return0 ;}
This sectionCodePgprot_noncached () in is a macro, which actually disables the cache and write buffer of the relevant page. Another macro with a slight limit is:
# Define pgprot_writecombine (prot) _ pgprot (pgprot_val (prot) &-l_pte_cacheable); no write buffer is prohibited
Besides rempa_pfn_range (),ProgramThe nopage () function implementing VMA generally provides a more flexible memory ing path for the device. When a page is missing, nopage () is automatically called by the kernel ,. This is because when a page exception occurs, the system will go through the following process:
1) Find the VMA of the virtual address with missing pages. 2) If necessary, allocate the directory table and page table on the middle page.
3) if the physical page table corresponding to the page table item does not exist, call the nopage () method of this VMA and return the page descriptor of the physical page.
4) Fill in the address of the physical page to the page table.
After nopage is implemented, the user space can call the mremap () system to re-bind the address bound to the ing area. The following is a typical example of using nopage () in the device driver:
Static Int Xxx_mmap (Struct File * filp, Struct Vm_area_struct * VMA );{ Unsigned Long Offset = VMA-> vm_pgoff <page_offset; If (Offset> = _ Pa (high_memory) | (filp-> flags & o_sync) VMA-> vm_flags | = vm_io; VMA-> vm_ops = & xxx_nopage_vm_ops; xxx_vma_open (VMA ); Return 0 ;} Struct Page * xxx_vma_nopage ( Struct Vm_area_struct * VMA, Unsigned Long Address,Int * Type ){ Struct Page * pageptr; Unsigned Long Offset = VMA-> vm_pgoff <page_shift; Unsigned Long Physaddr = address-VMA-> vm_start + offset; // Physical memory Unsigned Long Pageframe = physaddr> page_shift; // Page frame number If (! Pfn_valid (pageframe )) // The page frame number is valid. Return Nopage_sigbus; pageptr = pfn_to_page (pageframe ); // Page frame number-> page Descriptor Get_page (pageptr ); // Get the page and add the page usage count If (Type) * type = vm_fault_minor; Return Pageptr; // Return page Descriptor
}
The above function maps the regular memory and returns a page descriptor that can be used to expand or reduce the memory area of the ing. It can be seen that a big difference between nopage () and remap_pfn_range () is remap_pfn.
_ Range () is generally used for device memory ing, while nopage () can also be used for Ram ing.
Mr. Wang, I watched this Section together with the previous one. I can take a break. If you take a look at it, you will not bother me. I will call you for dinner at night ..