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,最后会不会同步到磁盘呢?
未完待续