About mmap () function of the user and drive a little summary
Introduction: the memory map, in a nutshell is to map the region of memory user space to kernel space, the mapping is successful, the user can modify this memory area is reflected directly into the kernel space, the same kernel space to this area modifications are a direct reflection of user space. Then for kernel space <----> requires user space therebetween large, then the operation efficiency data transmission is very high.
The following is a diagram of a general mapping file to the memory area of the user space.
Figure 1:
User space:
mmap function is a UNIX / Linux system calls in, details refer to "Unix Netword programming" Volume II 12.2.
In order for the shared memory is not entirely designed mmap system call. It itself provides a way different from the general access to common files, the process can be like memory read and write operations on a regular file. Or Posix and System V IPC shared memory is used solely for the purpose of sharing, of course, mmap () shared memory is one of its main applications.
mmap system call allows processes between shared memory by mapping with a common file. After the general file is mapped into the process address space, the process can be as accessible as normal memory access to files, do not have to call the read (), write () and so on. mmap not allocate space, just to map the file into the address space of the calling process's (but it will takes up your virutal memory), then you can write file operations such as memcpy instead of write () a. After writing, the contents of memory and not immediately update to the file, but there is a delay, you can call msync () explicitly synchronize it, so that you will be able to save what is written immediately to the file. this It should be relevant and drive. But to write in this way by mmap file can not increase the length of the file, because the length of time to be mapped in a call to mmap () of the decision. If you want to cancel a memory-mapped, you can call munmap () to cancel the memory mapping
[cpp] view plain copy
- void * mmap(void *start, size_t length, int prot , int flags, int fd, off_t offset)
mmap is used to map the file into memory space, simply mmap contents of a file is to do an in-memory image inside. After the mapping is successful, the user can modify this memory area is reflected directly into the kernel space, likewise, to modify the kernel space of this region is also a direct reflection of user space. Then for kernel space <----> requires user space therebetween large, then the operation efficiency data transmission is very high.
start: start address to be mapped to a memory area, usually with a NULL (NULL is, 0). NULL means the kernel is specified by the memory address
length: to be mapped memory area the size of
prot: the desired memory protection flags, can not conflict with the open mode of the file. Is one of the following values may reasonably be combined by calculation or
PROT_EXEC // page content may be performed
PROT_READ // pages may be read
PROT_WRITE // pages may be written
PROT_NONE // non-accessible page
flags: Specifies type mapping object, mapping options and whether the map page can be shared. Its value may be one or more of the following bit combination
MAP_FIXED: mapping using the specified start address, if specified by the start and len parameters in the memory area overlapping the existing mapping space, the overlapped portion will be discarded. If the specified start address is not available, the operation will fail. And the starting address must fall on the border of the page.
MAP_SHARED: write data to the mapped region will be copied back inside files, but also allows other processes mapping the file sharing.
MAP_PRIVATE: establish a written copy when private mapping. Write memory area will not affect the original file. This flag and the flags above are mutually exclusive and can only use one of them.
MAP_DENYWRITE: This flag is ignored.
MAP_EXECUTABLE: ditto
MAP_NORESERVE: Do not leave space for the exchange of maps. When swap space is reserved to modify the mapping area could be guaranteed. When swap space is not reserved, and out of memory, changes to the mapped region will cause a segmentation violation signal.
MAP_LOCKED: Lock the page mapping area, thereby preventing the page is swapped out of memory.
MAP_GROWSDOWN: for the stack, to tell the kernel VM system, mapping area can be extended downward.
MAP_ANONYMOUS: anonymous mapping, mapping area not associated with any file.
MAP_ANON: MAP_ANONYMOUS another name, no longer in use.
MAP_FILE: compatible flag is ignored.
MAP_32BIT: mapping the area on the lower 2GB of the process address space will be ignored when MAP_FIXED specified. This flag is currently only supported on x86-64 platform.
MAP_POPULATE: ready for the file mapping page table read-ahead by the way. Subsequent access mapping zones will not be blocked pages violation.
MAP_NONBLOCK: MAP_POPULATE and when used with the only meaningful. Do not read ahead, build page table entry only for pages that already exists in memory.
fd: file descriptor (returned by the open function)
offset: represents a mapping object (i.e., files) enantiomer from there, often with zeros. This value should be an integer multiple of a size of PAGE_SIZE
return instructions
when executed successfully, mmap () returns a pointer to the mapped region, munmap () returns 0. Failure, mmap () Returns MAP_FAILED [a value (void *) - 1], munmap -1. errno is set to one of the following values
EACCES: Access error
EAGAIN: file is locked, or too much memory has been locked
EBADF: fd is not a valid file descriptor
EINVAL: one or more parameters are invalid
ENFILE: The system has reached the limit of open files
ENODEV: Specifies the file where the file system It does not support memory mapping
ENOMEM: Out of memory, or process have exceeded the maximum number of memory-mapped
EPERM: lack of power, operation is not allowed
ETXTBSY: open the file has been written, specifying MAP_DENYWRITE flag
SIGSEGV: try to write to a read-only area
SIGBUS: try to access the memory area is not part of the process
[cpp] view plain copy
- int munmap(void *start, size_t length)
start: starting address you want to cancel mapped memory area
length: To cancel the memory size of the map area.
Returning to the description
munmap successful execution () returns 0. Munmap return on failure -1.
Int msync (const void * Start, size_t length, int flags);
changes to the contents of the memory map does not update the file immediately, but there is a delay, you can call msync () explicitly synchronize it, so you can save memory update file immediately to
start: to start address of the memory region mapped synchronized.
length: memory size of the area to be synchronized
flag: flags can be one of three values:
MS_ASYNC: Please Kernel soon to write data.
MS_SYNC: msync return before the end of the write data.
MS_INVALIDATE: let the heart decide whether written, used only in special circumstances
Drive space:
3.1, the basic process
first of all, for some drivers allocate memory, then the user through the process of library function mmap () to tell the kernel how much memory you want mapped to kernel space, the kernel calls after a series of function calls the corresponding driver file_operation specified in the mmap function, call remap_pfn_range in the function () to establish the mapping.
3.2, maps the
first in the driver allocates an amount of memory, then the user process by mmap () the user space memory page size is also mapped to kernel space memory this page. After the mapping is done, this driver is to write 10 bytes of data memory, the user process will display the data out.
driver:
[cpp] view plain copy
- #include <linux/miscdevice.h>
- #include <linux/delay.h>
- #include <linux/kernel.h>
- #include <linux/module.h>
- #include <linux/init.h>
- #include <linux/mm.h>
- #include <linux/fs.h>
- #include <linux/types.h>
- #include <linux/delay.h>
- #include <linux/moduleparam.h>
- #include <linux/slab.h>
- #include <linux/errno.h>
- #include <linux/ioctl.h>
- #include <linux/cdev.h>
- #include <linux/string.h>
- #include <linux/list.h>
- #include <linux/pci.h>
- #include <linux/gpio.h>
- #define DEVICE_NAME "mymap"
- static unsigned char array[10]={0,1,2,3,4,5,6,7,8,9};
- static unsigned char *buffer;
- static int my_open(struct inode *inode, struct file *file)
- {
- return 0;
- }
- static int my_map(struct file *filp, struct vm_area_struct *vma)
- {
- unsigned long page;
- unsigned char i;
- unsigned long start = (unsigned long)vma->vm_start;
- //unsigned long end = (unsigned long)vma->vm_end;
- unsigned long size = (unsigned long)(vma->vm_end - vma->vm_start);
- // get the physical address
- page = virt_to_phys(buffer);
- // to map a virtual memory area vma user space to the period of continuous physical page to page beginning
- IF (of remap_pfn_range (VMA, Start, Page >> PAGE_SHIFT, size, PAGE_SHARED)) // The third parameter is the page frame number obtained by the physical address right PAGE_SHIFT
- return -1;
- // write to the memory 10 bytes of data
- for(i=0;i<10;i++)
- buffer[i] = array[i];
- return 0;
- }
- static struct file_operations dev_fops = {
- .owner = THIS_MODULE,
- .open = my_open,
- .mmap = my_map,
- };
- static struct miscdevice misc = {
- .minor = MISC_DYNAMIC_MINOR,
- .name = DEVICE_NAME,
- .fops = &dev_fops,
- };
- static int __init dev_init(void)
- {
- an int Ret;
- // Register hybrid device
- ret = misc_register(&misc);
- // memory allocation
- buffer = (unsigned char *)kmalloc(PAGE_SIZE,GFP_KERNEL);
- // set the memory segment reserved
- SetPageReserved(virt_to_page(buffer));
- Return the right;
- }
- static void __exit dev_exit(void)
- {
- // write-off equipment
- misc_deregister(&misc);
- // clear reservations
- ClearPageReserved(virt_to_page(buffer));
- // release memory
- kfree(buffer);
- }
- module_init(dev_init);
- module_exit(dev_exit);
- MODULE_LICENSE("GPL");
- MODULE_AUTHOR("LKN@SCUT");
Application examples:
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <linux/fb.h>
#include <sys/mman.h>
#include <sys/ioctl.h>
#define PAGE_SIZE 4096
int main(int argc , char *argv[])
{
int fd;
int i;
unsigned char *p_map;
// Open device
fd = open("/dev/mymap",O_RDWR);
if(fd < 0)
{
printf("open fail\n");
exit(1);
}
// memory map
p_map = (unsigned char *)mmap(0, PAGE_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED,fd, 0);
if(p_map == MAP_FAILED)
{
printf("mmap fail\n");
goto here;
}
10 bytes before the contents of the memory map is printed //
for(i=0;i<10;i++)
printf("%d\n",p_map[i]);
here:
munmap(p_map, PAGE_SIZE);
return 0;
}