mmap () function:
void *mmap(void* addr,size_t length,int port,int flags,int fd,off_t offset);
Returns: Success: returns the first address mapping area created; failure: MAP_FAILED Macro
parameter:
addr: the establishment of the first address mapping area, determined by the linux kernel. When used directly pass NULL;
length: To create the size of the map area
port: mapping area authority PROT _READ, PROT_WRITE, PROT _READ | PROTWRITE
flags: Flag parameter (often used to set the update physical area, set the share, create an anonymous mapping area)
MAP_SHARED: Operation will be made to the physical mapping area reflecting device
MAP_PRIVATE: modify the mapping area made will not be reflected to the physical device.
fd: file descriptor used to build the mapping area
offset: offset map file (4K integer multiple)
/*** mmap.c ***/ #include<stdio.h> #include<fcntl.h> #include<unistd.h> #include<string.h> #include<stdlib.h> #include<sys/mman.h> int main() { int len,ret; char *p = NULL; int fd = open("mytest.txt",O_CREAT|O_RDWR,0644); if(fd < 0 ) { perror("open error:"); exit(1); } len = ftruncate(fd,4); if(-1 == len) { perror("ftruncate error:"); exit(1); } p = mmap(NULL,4,PROT_READ|PROT_WRITE,MAP_SHARED,fd,0); if(p == MAP_FAILED) { perror("mmap error:"); exit(1); } strcpy(p,"abc"); ret = munmap(p,4); if(-1 == ret) { perror("mmap error:"); exit(1); } close(fd); return 0; }
operation result:
ubuntu1604 personality @: ~ / wangqinghe / linux / 20190807 $ gcc mmap.c -that Map
ubuntu1604@ubuntu:~/wangqinghe/linux/20190807$ ./mmap
ubuntu1604@ubuntu:~/wangqinghe/linux/20190807$ cat mytest.txt
abc
mmap note the following during use:
- The process of creating a mapping zone, implies a read operation on the mapping file.
- When MAP_SHARED, it is required: Permission mapping area of <= permission to open files (for the protection of mapped areas). The MAP_PRIVATE then it does not matter, because the time limit for memory mmap of authority.
- Release and file mapping area closed unrelated. As long as the mapping is successful, the file can be closed immediately.
- Special Note: When mapping file size is zero, you can not create a mapping area. So: there must be mapped file for the actual size. Often bus error occurs when mmap use, usually because the shared file storage space caused.
- munmap incoming address must be mmap return address, and resolutely put an end to the operation pointer ++
- If a file offset, then the value must be an integer multiple of 4K
- mmap creates a mapping error high probability area, be sure to check the return value to ensure the success of re-mapping area to establish follow-up action.
mmap-process communication between father and son:
Inode file attributes
struct stat
{
Memory pointer address;
size;
Authority;
Types of;
So who;
}
/*** mmap_fork.c ***/ #include<stdio.h> #include<stdlib.h> #include<unistd.h> #include<fcntl.h> #include<sys/mman.h> #include<sys/wait.h> int var = 100; int main() { int *p; pid_t pid; int fd; fd = open("temp",O_RDWR|O_CREAT|O_TRUNC,0644); if(fd < 0) { perror("open error"); exit(1); } unlink("temp"); ftruncate(fd,4); p = (int*)mmap(NULL,4,PROT_READ|PROT_WRITE,MAP_SHARED,fd,0); if(p == MAP_FAILED) { perror("mmap error"); exit(1); } close(fd); pid = fork(); if(0 == pid) { *p = 2000; var = 1000; printf("child, *p = %d, var = %d\n",*p,var); } else { sleep(1); printf("parent, *p = %d, var = %d\n",*p,var); wait(NULL); int ret = munmap(p,4); if(-1 == ret) { perror("munmap error"); exit(1); } } return 0; }
operation result:
ubuntu1604@ubuntu:~/wangqinghe/linux/20190807$ gcc mmap_fork.c -o mmap_fork
ubuntu1604@ubuntu:~/wangqinghe/linux/20190807$ ./mmap_fork
child, *p = 2000, var = 1000
parent, *p = 2000, var = 100
create anonymous mmap mapped area
/*** fork_mmap_linux.c ***/ #include<stdio.h> #include<stdlib.h> #include<unistd.h> #include<fcntl.h> #include<sys/mman.h> #include<sys/wait.h> int var = 100; int main() { int *p; pid_t pid; p = (int*)mmap(NULL,4,PROT_READ|PROT_WRITE,MAP_SHARED | MAP_ANON,-1,0); if(p == MAP_FAILED) { perror("mmap error"); exit(1); } pid = fork(); if(0 == pid) { var = 1000; *p = 2000; printf("child, *p = %d,var = %d\n",*p,var); } else { sleep(1); // printf("parent,*p = %d\n",*p); printf("child, *p = %d,var = %d\n",*p,var); wait(NULL); int ret = munmap(p,4); if(-1 == ret) { perror("munmap error"); exit(1); } } return 0; }
operation result:
ubuntu1604@ubuntu:~/wangqinghe/linux/20190807$ gcc fork_map_linux.c -o fork_map_linux
ubuntu1604 @ ubuntu: ~ / wangqinghe / linux / 20190807 $ ./fork_map_linux
child, *p = 2000,var = 1000
child, *p = 2000,var = 100
Note: MAP_ANONYMOUS MAP_ANON two macros and linux operating system specific macros, then Unix-based systems without the macro definition, the following steps may be used to complete the establishment of the anonymous mapping area.
- fd = open(“/dev/zero”,O_RDWR);
- p = mmap(NULL,size,PROT_READ|PROT_WRITE,MMAP_SHARED,fd,0);
/*** fork_map_anon.c ***/ #include<stdio.h> #include<stdlib.h> #include<unistd.h> #include<fcntl.h> #include<sys/mman.h> #include<sys/wait.h> int var = 100; int main() { int *p; pid_t pid; int fd = open("/dev/zero",O_RDWR); p = (int*)mmap(NULL,4,PROT_READ|PROT_WRITE,MAP_SHARED,fd,0); if(p == MAP_FAILED) { perror("mmap error"); exit(1); } pid = fork(); if(0 == pid) { var = 1000; *p = 2000; printf("child, *p = %d,var = %d\n",*p,var); } else { sleep(1); // printf("parent,*p = %d\n",*p); printf("child, *p = %d,var = %d\n",*p,var); wait(NULL); int ret = munmap(p,4); if(-1 == ret) { perror("munmap error"); exit(1); } } return 0; }
operation result:
buntu1604@ubuntu:~/wangqinghe/linux/20190807$ gcc fork_map.c -o fork_map
ubuntu1604@ubuntu:~/wangqinghe/linux/20190807$ ./fork_map
child, *p = 2000,var = 1000
child, *p = 2000,var = 100
mmap no blood relationship between the process of communication:
/*** mmap_w.c ***/ #include<stdio.h> #include<sys/stat.h> #include<fcntl.h> #include<unistd.h> #include<stdlib.h> #include<sys/mman.h> #include<string.h> struct STU { int id; char name[20]; char sex; }; void sys_err(char *str) { perror(str); exit(1); } int main(int argc,char ** argv) { int fd; struct STU student = {10,"xiaoming",'m'}; char *mm; if(argc < 2) { printf("./a.out file_shared\n"); exit(-1); } fd = open(argv[1],O_RDWR | O_CREAT,0664); ftruncate(fd,sizeof(student)); mm = mmap(NULL,sizeof(student),PROT_READ|PROT_WRITE,MAP_SHARED,fd,0); if(mm == MAP_FAILED) { sys_err("mmap error"); } close(fd); while(1) { memcpy(mm,&student,sizeof(student)); student.id++; sleep(2); } munmap(mm,sizeof(student)); return 0; }
/*** mmap_r.c ***/ #include<stdio.h> #include<sys/stat.h> #include<fcntl.h> #include<unistd.h> #include<stdlib.h> #include<sys/mman.h> #include<string.h> struct STU { int id; char name[20]; char sex; }; void sys_err(char *str) { perror(str); exit(1); } int main(int argc,char ** argv) { int fd; struct STU student; struct STU *mm; if(argc < 2) { printf("./a.out file_shared\n"); exit(-1); } fd = open(argv[1],O_RDONLY); if(-1 == fd) sys_err("open error"); mm = mmap(NULL,sizeof(student),PROT_READ,MAP_SHARED,fd,0); if(mm == MAP_FAILED) { sys_err("mmap error"); } close(fd); while(1) { printf("id=%d,name = %s,%c\n",mm->id,mm->name,mm->sex); sleep(2); } munmap(mm,sizeof(student)); return 0; }