目录
内存映射概念:
函数原型:
内存映射步骤:
主要功能 :
系统调用mmap用于共享内存的两种方式:
使用普通文件提供的内存映射:
使用特殊文件提供匿名内存映射:
注意事项 :
内存映射概念:
mmap是一个系统调用,用于在内存和文件之间创建映射。它允许将文件的一部分或整个文件映射到进程的地址空间,从而使进程可以直接访问文件的内容,就像访问内存一样。
通过mmap,你可以将文件映射为一个连续的字节序列,然后可以使用指针对其进行读取和写入操作。这种直接内存访问的方式可以提供高效的文件操作,并且可以方便地在内存和文件之间共享数据。
在C/C++中, mmap函数通常使用 <sys/mman.h>头文件进行声明
mmap将一个文件或者其他对象映射进内存。文件被映射到多个页上,如果文件的大小不是所有页的大小之和,最后一个页不被使用的空间将会清零。
函数原型:
#include <sys/mman.h>
void* mmap(void* addr, size_t length, int prot, int flags, int fd, off_t offset);
void* munmap(void* addr, size_t length);
内存映射步骤:
- 用open系统调用打开文件,并返回描述符 fd
- 用 mmap 建立内存映射,并返回映射首地址指针 addr
- 对映射(文件)进行各种操作,显示(printf),修改(sprintf)
- 用munmap(void *addr,size_t length)关闭内存映射
- 用 close系统调用关闭文件 fd
主要功能 :
- 将一个普通文件映射到内存中,通常在需要对文件进行频繁读写时使用,这样用内存读写取代 I/0 读写,以获得较高的性能;
- 将特殊文件进行匿名内存映射,可以为关联进程提供共享内存空间;
- 为无关联的进程提供共享内存空间,一般也是将一个普通文件映射到内存中。
系统调用mmap用于共享内存的两种方式:
使用普通文件提供的内存映射:
适用于任何进程之间。此时,需要打开或创建一个文件,然后再调用mmap()典型调用代码如下:
fd=open(name,flag,mode); if(fd<0) ...
ptr=mmap(NULL,len,PROT_READ|PROT_WRITE,MAP_SHAREDfd,0);
使用特殊文件提供匿名内存映射:
适用于具有亲缘关系的进程之间。由于父子进程特殊的亲缘关系,在父进程中先调用mmap(),然后调用 fork()。那么在调用fork()之后,子进程继承父进程匿名映射后的地址空间,同样也继承mmap返回的地址,这样,父子进程就可以通过映射区域进行通信了。注意,这里不是一般的继承关系。一般来说,子进程单独维护从父进程继承下来的一些变量。而mmap返回的地址,却由父子进程共同维护。 对于具有亲缘关系的进程实现共享内存最好的方式应该是采用匿名内存映射的方式。此时,不必指定具体的文件,只要设置相应的标志即可。
注意事项 :
- 创建映射区的过程中,隐含着一次对映射文件的读操作。
- 当MAP SHARED 时,要求:映射区的权限应<= 文件打开的权限(出于对映射区的保护)。而MAPPRIVATE 则无所谓,因为mmap 中的权限是对内存的限制。
- 映射区的释放与文件关闭无关。只要映射建立成功,文件可以立即关闭。
- 特别注意,当映射文件大小为0时,不能创建映射区。所以:用于映射的文件必须要有实际大小! mmap 使用时常常会出现总线错误,通常是由于共享文件存储空间大小引起的。如,400字节大小的文件,在建立映射区时 offset 4096 字节,则会报出总线错
- munmap 传入的地址一定是mmap 的返回地址。坚决杜绝指针++操作。
- 如果文件偏移量必须为 4K 的整数倍
- mmap 创建映射区出错概率非常高,一定要检查返回值,确保映射区建立成功再进行后续操作。