"Let me tell you nothing, Mr. Wang. I'm happy now, but sadly: In this last chapter, I'm talking about it with treasure, now, I am paying back my account). I like every lecture. I know that I am a little closer to the end. I just need to pass this article over and enter the next step, that is the time when my skin is blowing through the sky. "looking at Wang's expectations and skeptical eyes, I lost my old style.
"It's okay, Mr. Tao. Actually, it's true that I didn't comfort you. I didn't understand anything from the very beginning. Now I am also an entry-level expert, you have brought it with your hands. I have already put it in your favor. You can rest assured that you will teach it as much as you can, but you will not, I hear from you, "said Xiao Wang.
"Well, you are so nice. It seems that I am not mistaken about you. Well, continue the course "...
Generally, it is impossible for a user space to directly access the device, but the device driverProgramMMAP () can be implemented. This function allows the user space to directly access the physical address of the device. In fact, MMAP () s implements such a ing process. It associates a piece of memory in the user space with the device memory. When the user accesses the address range of the user space, in fact, it will be converted into access to the device.
MMP () must be mapped in page_size units. In fact, the memory can only be mapped in pages. To map addresses that are not an integer multiple of page_size, you must first align pages, forcibly Use Page
Ing the multiples of _ size. In the driver, the prototype of the matrix function is as follows: int (* MMP) (struct file *, struct vm_area_struct *). The Mechanism Implemented by this function is to create a page table and fill in the VMA struct.
Vm_operations_struct pointer, vm_area_struct is used to describe a virtual memory area. The struct is as follows:
Struct Vm_area_struct { Struct Mm_struct * vm_mm; // Address space Unsigned Long Vm_start; // Start the virtual address Unsigned Long Vm_end; // End the virtual address Struct Vm_area_struct * vm_next; pgprot_t vm_page_prot; // Access permission Unsigned Long Vm_flags; // Flag ... Struct Vm_operations_struct * vm_ops;// Operate VMA function set pointer Unsigned Long Vm_pgoff; // Offset (page frame number) Struct File * vm_file; Void * Vm_private_data ;...};
The vm_ops Member points to the VMA operation set. The struct is defined as follows:
Struct Vm_operations_struct { Void (* Open )( Struct Vm_area_struct * area ); Void (* Close )(Struct Vm_area_struct * area ); Struct Page * (* nopage )( Struct Vm_area_struct * area, Unsigned Long Address, Int * Type ); Int (* Populate )( Struct Vm_area_struct * area, Unsigned Long Address, Unsigned Long Len, pgprot_t Prot,Unsigned Long Pgoff, Int Nonblock);...}; after a VMA is generated in the kernel, it will call the open () function of the VMA.
The MMAP () function in the driver will be called when the user calls the MMAP () system. When the user calls MMAP (), the kernel will perform the following processing:
1) Search for a VMA in the virtual space of the process.
2) map this VMA.
3) if the device driver or file_operations of the file system defines the MMAP () operation, call it.
4) Insert the VMA into the VMA linked list of the process.
The first parameter of the MMAP () function in file_operations is the VMA found in step 1. The memory for the MMAP () System Call ing can be unbound from the munmap. The function is prototype as follows:
Int munmap (caddr_t ADDR, size_t Len );
However, it should be noted that after the user calls the MMAP () system, although VMA is generated before the MMAP () of the device driver file operation struct is called, the kernel does not call the VMA open
To illustrate the problem, a vm_operations_struct operation example is provided:
Static Int Xxx_mmp ( Struct File * filp, Struct Vm_area_struct * VMA ){ If (Remap_pfn_range (VMA, VMA-> vm_start, Vm-> vm_pgoff, VMA-> vm_end-VMA-> Start, VMA-> vm_page_prot )) // Create a page table Return -Eagain; VMA-> vm_ops = & xxx_remap_vm_ops; xxx_vma_open (VMA ); Return 0 ;} Void Xxx_vma_open ( Struct Vm_area_struct * VMA) // VMA open the Function {... Printk (kern_notice"Xxx VMA open, virt % lx, Phys % 1x \ n ", VMA-> vm_start, VMA-> vm_pgoff page_shift );} Void Xxx_vma_close ( Struct Vm_area_struct * VMA) // Disable the VMA Function {... Printk (kern_notice" Xxx VMA close. \ n ");} Static Struct Vm_operation_struct xxx_remap_vm_ops = // VM operation structure {. Open = Xxx_vma_open ,. Close = Xxx_vma_close ,...}
In this sectionCodeTo create a page table. We mentioned earlier that kmalloc is used to apply for memory in the kernel space. To map this part of memory to the user space, you can use mem_map
_ Reserve () is called after it is set to retained. How can we proceed with the next set.