一、内存映射
1)原理
文件和内存映射:就是将普通文件映射到内存中,普通文件映射到进程地址空间后,进程可以像访问普通内存一样对文件进行访问,不必再调用read或write等操作。系统提供了函数mmap将普通磁盘文件映射到内存中;
2)函数讲解
void* mmap(void* start, size_t length,int prot,int flags, int fd,
off_t offset);
- 参数讲解
①start:映射区的起始地址,通常为NULL或0,表示由系统决定映射到什么地址; ②length:表示映射数据的长度,即文件需要映射到内存中的数据的大小 ③prot:表示映射区的保护方式
PROT_EXEC:映射区可被执行
PROT_READ:映射区可被读取
PROT_WRITE:映射区可写入
PROT_NONE:映射区不可访问
④flags指定映射区的对象的类型、映射选项和映射页是否共享。(值可以使组合)
MAP_FIXED
MAP:_SHARED
MAP:RIVATE:
MAP_ANONYOUS:
A:DENYWRITE:
AP_LOCKED:
3)代码使用实例
#include <sys/mman.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>
int main(int argc,char** argv)
{
int fd = 0;
char* mmaped = NULL;
char* p = NULL;
int length = 1024;
void* start_addr = 0;
fd = open(argv[1],O_RDWR|O_CREAT,S_IRUSR|S_IWUSR);
length = lseek(fd,1,SEEK_END);
write(fd,"\0",1);//在文件末尾最后添加一个空字符,以便下面的printf正常工作
lseek(fd,0,SEEK_SET);
start_addr = (void*)0x80000;
mmaped = (char*)mmap(start_addr,length,PROT_READ|PROT_WRITE,MAP_SHARED,fd,0);
//PROT_READ|PROT_WRITE 允许读写
//MAP_SHARED 允许其他进程访问此内存区域
//打印映射区域(也就是使用映射区域)
printf("%s\n",mmaped);//传递的参数最好是文本文件的名字
while((p = strstr(mmaped,"hello"))) //文件中要求是有hello的字段
{
memcpy(p,"linux",5); //把hello改成linux
p+=5;
}
close(fd);
munmap(mmap,length);
return 0;
}
g++ test.cpp -o test ./test myfile.txt
二、内存映射和共享内存的比较
1)前情提要
正文6:System V共享内存(修正版)及ftok函数讲解 正文9:共享内存区和posix共享内存介绍(10/9)
2)比较
-
mmap 1)原理:在磁盘上简历一个文件,没每个进程存储器单独开辟一个空间来进行映射。如果是多进程,那么对实际的物理存储器(主存)消耗不会太大。 2)与在内存保存的区别:mmap保存的位置 是实际磁盘,实际存储没有放到主存上 3)优点:存储量可以很大(可以大于内存大小) 4)缺点:进程间读取速度和写入速度要比主存的慢 -
shm机制 1)原理:每个进程的共享内存都直接映射到实际物理存储器里面。共享内存允许两个或多个进程共享一个给定的存储区,因为数据不需要来回复制,所以是最快的进程间通信方式。 2)保存位置:shm保存到物理存储器(主存),实际的存储量直接被主存的大小决定 3)优点:进程间访问速度和读写速度比磁盘要快, 4)缺点:存储量不能大于主存大小 5)实现方式:①mmap映射普通文件(或匿名映射)机制实现;②也可以通过系统V共享内存机制实现。(往往通过与信号灯等同步机制一起使用)
3)总结(更多比较在上面的文章)
如果分配的存储量不大,且对读写、访问速度要求高,就用shm;如果存储量非常大,对速度要求不高用mmap
|