Linux进程之间的通信--内存映射区mmap

mmap创建内存映射区域

作用:将磁盘文件的数据映射到内存,用户通过修改内存就能修改磁盘文件
函数原型:

 #include <sys/mman.h>

void *mmap(
		void *addr,//映射区首地址,传NULL 
		size_t length, //映射区的大小
		int prot,      //映射区权限
		int flags,     //标志位参数
        int fd,        //文件描述符
        off_t offset   //映射文件的偏移量
);
size_t length;
	100byte-4k
	不能为0
int prot;           //映射区权限
	PROT_READ---映射区必须要有读权限
	PROT_WRITE
	PROT_READ | PROT_WRITE
int flags;          //标志位参数
	MAP_SHARED
		修改了内存数据会同步到磁盘
	MAP_PRIVATE
		修改了内存数据不会同步到磁盘
int fd;             //文件描述符
	要映射文件的fd
	要先通过open()得到
off_t offset        //映射文件的偏移量
	映射的时候文件指针偏移量
返回值:
	调用成功---映射区的首地址
	调用失败---MAP_FAILED
munmap-释放内存映射区

函数原型

#include <sys/mman.h>
int munmap(void *addr, size_t length);
addr--mmap的返回值,映射区的首地址
length--mmap的第二个参数,映射区长度

代码示例:

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

int main(){
        int fd=open("test.txt",O_RDWR);
        if(fd<0){
                perror("open error");
                exit(1);
        }
        int len=lseek(fd,0,SEEK_END);
        void *p=mmap(NULL,len,PROT_READ | PROT_WRITE,MAP_SHARED,fd,0);
        if(p==MAP_FAILED){
                perror("mmap error");
                exit(1);
        }
        printf("%s",(char *)p);

        int ret=munmap(p,len);
        if(ret==-1){
                perror("munmap error");
                exit(1);
        }
        close(fd);
        return 0;
}

两个没有血缘关系进程之间的通信程序示例:

//程序1
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<unistd.h>
#include<sys/types.h>
#include<sys/mman.h>
#include<fcntl.h>

int main(int argc,char *argv[]){
		//这两个进程通过同一个文件来进行通信。
        int fd=open("connect",O_RDWR | O_CREAT,0664);//新创建了一个文件大小为0
        ftruncate(fd,4096);//将文件大小扩扩展到4096,使用lseek也行,但是不要忘了写一下
        int len=lseek(fd,0,SEEK_END);//获取文件长度
		//向内存中映射
        void *ptr=mmap(NULL,
        			len,/*要映射的文件大小*/
        			PROT_READ | PROT_WRITE/*读写权限*/,
        			MAP_SHARED/*内存磁盘同步*/,
        			fd,/*文件描述符*/
        			0/*4096的整数倍*/
        			);
	
        if(ptr==MAP_FAILED){
                perror("mmap");
                exit(1);
        }
        while(1){
                sleep(1);
                //这个时候就可以像操作内存一样操作数了
                printf("%s\n",(char *)ptr);//从这个文件开始读
        }
        //释放
        int ret=munmap(ptr,len);//释放
        if(ret==-1){
                perror("munmap");
                exit(1);
        }
        return 0;
}

//程序二
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<unistd.h>
#include<sys/types.h>
#include<sys/mman.h>
#include<fcntl.h>
int main(int argc,char *argv[]){
        int fd=open("connect",O_RDWR | O_CREAT,0664);
        void *ptr=mmap(NULL,4096,PROT_READ|PROT_WRITE,MAP_SHARED,fd,0);
        if(ptr==MAP_FAILED){
                perror("mmap");
                exit(1);
        }
        while(1){
                char * p=(char*)ptr;
                strcpy(p,"我是从程序二来的\n");//操作内存
                sleep(2);
        }
        int ret=munmap(ptr,4096);
        if(ret==-1){
                perror("munmap");
                exit(1);
        }
        return 0;
}

几个问题

如果对mmap的返回值(ptr)做++操作(ptr++),munmap是否能够成功?
不能,你对数组的名++怎么样

如果open时O_RDONLY,mmap时prot参数指定 PROT_READ | PROT_WRITE会怎么样?
如果mmap是readwrite 那么open的时候就必须是读写的

如果文件偏移量为1000怎么样?
必须是4096的整数倍

如果不检测mmap的返回值会怎么样?
映射失败了,你不知道

Mmap什么时候会调用失败?
1、 第二个参数为0
2、 必须指定prot_read权限
fd对应的打开权限必须大于等于port权限
3、 偏移量:必须是4096的整数倍

可以open的时候,O_CREAT一个新文件来创建映射区吗?
要映射的文件大小不确定不能为0,可以为100,就可能会盛不下,内存同步过来的数据,但是映射区大小必须是4096的整数倍
可以,需要做文件拓展,
lseek,记得扩展完要写一下
truncate(path,length)

mmap关闭文件描述符,对mmap映射区有没有影响。
没有,有内存指针了呀

对ptr越界操作会怎么样?
段错误

如果没有用MAP_SHARED,最后会不会同步到磁盘呢?
未完待续

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值