mmap通信

mmap共享映射区
void *mmap(void *addr,size_t length,int prot,int flags,int fd,off_t offset);
addr 传NULL
length 长度
prot PROT_READ可读 PROT_WRITE可写
flags MAP_SHARED共享的,修改内存会影响原文件 MAP_PRIVATE私有的
fd 文件描述符,open打开一个文件
offset 偏移量
返回值:成功返回可用的内存首地址,失败返回MAP_FAILED

释放映射区
int munmap(void *addr,size_t length);
addr 传mmap的返回值
length mmap创建的长度
返回值:成功返回0,失败返回-1

mmap.c

#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <string.h>

int main()
{
    int fd = open("mem.txt",O_RDWR);//创建并且截断文件
    //int fd = open("mem.txt",O_RDWR|O_CREAT|O_TRUNC,0664);//创建并且截断文件

    ftruncate(fd,8);   
    //创建映射区
   char *mem = mmap(NULL,20,PROT_READ|PROT_WRITE,MAP_SHARED,fd,0);
    //char *mem = mmap(NULL,8,PROT_READ|PROT_WRITE,MAP_PRIVATE,fd,0);

    if(mem == MAP_FAILED){
        perror("mmap err");
        return -1;
    }
    close(fd);
    //拷贝数据
    strcpy(mem,"helloworld");
//    mem++;
    //释放mmap
    if(munmap(mem,20) < 0){
        perror("munmap err");
    }
    return 0;
}

mmap九问:
1.如果更改mem变量的地址,释放的时候munmap,传入mem能成功吗?(不能)
2.如果对mem越界操作会怎么样?(文件大小对映射区有影响,尽量避免)
3.如果文件偏移量填任意数会怎么样?(offset必须是4k的整数倍)
4.如果文件描述符先关闭,对mmap映射有没有影响?(没有影响)
5.open的时候,可以新创建一个文件来创建映射区吗?(可以,文件大小不能为0)
6.open文件可以选择O_WRONLY吗?(不可以,Permission denied)
7.选择MAP_SHARED的时候,open文件选择O_RDONLY,prot可以选择PROT_READ|PROT_WRITE吗?(Permission denied,SHARED的时候,映射区的权限<=open文件的权限)
8.mmap什么情况会报错?(很多情况…)
9.如果不判断返回值会怎么样?(会死的很难看…)

用mmap实现父子进程通信
如果进程要通信flags必须设为MAP_SHARED

mmap_child.c

#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/mman.h>
#include <fcntl.h>
#include <sys/wait.h>

int main()
{
    // 先创建映射区
    int fd = open("mem.txt",O_RDWR);
    //int *mem = mmap(NULL,4,PROT_READ|PROT_WRITE,MAP_SHARED,fd,0);
    int *mem = mmap(NULL,4,PROT_READ|PROT_WRITE,MAP_PRIVATE,fd,0);
    if(mem == MAP_FAILED){
        perror("mmap err");
        return -1;
    }
    // fork子进程
    pid_t pid = fork();

    // 父进程和子进程交替修改数据
    if(pid == 0 ){
        //son 
        *mem = 100;
        printf("child,*mem = %d\n",*mem);
        sleep(3);
        printf("child,*mem = %d\n",*mem);
    }
    else if(pid > 0){
        //parent
        sleep(1);
        printf("parent,*mem=%d\n",*mem);
        *mem = 1001;
        printf("parent,*mem=%d\n",*mem);
        wait(NULL);
    }

    munmap(mem,4);
    close(fd);
    return 0;
}

匿名映射:无需打开文件即可创建映射区

mmap.anon.c

#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/mman.h>
#include <fcntl.h>
#include <sys/wait.h>

int main()
{
    int *mem = mmap(NULL,4,PROT_READ|PROT_WRITE,MAP_SHARED|MAP_ANON,-1,0);

    if(mem == MAP_FAILED){
        perror("mmap err");
        return -1;
    }

    pid_t pid = fork();

    if(pid == 0 ){
        //son 
        *mem = 101;
        printf("child,*mem=%d\n",*mem);
        sleep(3);
        printf("child,*mem=%d\n",*mem);
    }else if(pid > 0){
        //parent 
        sleep(1);
        printf("parent,*mem=%d\n",*mem);
        *mem = 10001;
        printf("parent,*mem=%d\n",*mem);
        wait(NULL);
    }

    munmap(mem,4);
    return 0;
}

mmap实现无血缘关系进程通信

mmap_w.c

#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/mman.h>
#include <fcntl.h>
#include <sys/wait.h>

typedef struct  _Student{
    int sid;
    char sname[20];
}Student;

int main(int argc,char *argv[])
{
    if(argc != 2){
        printf("./a.out filename\n");
        return -1;
    }
    
    // 1. open file 
    int fd = open(argv[1],O_RDWR|O_CREAT|O_TRUNC,0666);
    int length = sizeof(Student);

    ftruncate(fd,length);

    // 2. mmap
    Student * stu = mma(NULL,length,PROT_READ|PROT_WRITE,MAP_SHARED,fd,0);
    
    if(stu == MAP_FAILED){
        perror("mmap err");
        return -1;
    }
    int num = 1;
    // 3. 修改内存数据
    while(1){
        stu->sid = num;
        sprintf(stu->sname,"xiaoming-%03d",num++);
        sleep(1);//相当于每隔1s修改一次映射区的内容
    }
    // 4. 释放映射区和关闭文件描述符
    munmap(stu,length);
    close(fd);

    return 0;
}

mmap_r.c

#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/mman.h>
#include <fcntl.h>
#include <sys/wait.h>

typedef struct _Student{
    int sid;
    char sname[20];
}Student;

int main(int argc,char *argv[])
{
    //open file 
    int fd = open(argv[1],O_RDWR);
    //mmap 
    int length = sizeof(Student);
    Student *stu = mmap(NULL,length,PROT_READ|PROT_WRITE,MAP_SHARED,fd,0);
    if(stu == MAP_FAILED){
        perror("mmap err");
        return -1;
    }
    //read data 
    while(1){
        printf("sid=%d,sname=%s\n",stu->sid,stu->sname);
        sleep(1);
    }
    //close and munmap 
    munmap(stu,length);
    close(fd);
    return 0;
}

上一篇:安卓app开发!Android面试中常问的MMAP到底是啥东东?成功定级腾讯T3-2


下一篇:IPC - Unix - 共享内存