mmap可以把磁盘文件的一部分直接映射到内存,这样文件中的位置直接就有对应的内存地址,对文件的读写可以直接用指针来做而不需要read/write函数。
#include <sys/mman.h>
void *mmap(void *addr, size_t length, int prot, int flag, int fd, off_t offset);
int munmap(void *addr, size_t length);
addr:如果addr参数为NULL,内核会自己在进程地址空间中选择合适的地址建立映射。如果addr不是NULL,则给内核一个提示,应该从什么地址开始映射,内核会选择addr之上的某个合适的地址开始映射。建立映射后,真正的映射首地址可以通过返回值可以得到。
len:是需要映射的那一部分文件的长度。
offset:从文件的什么位置开始映射,必须是页大小的整数倍。
fd:该文件的描述符。
prot有四种取值:
PROT_EXEC 表示映射的这一段可执行,例如映射共享库
PROT_READ 表示映射的这一段可读
PROT_WRITE 表示映射的这一段可写
PROT_NONE 表示映射的这一段不可访问
flag:
MAP_SHARED 多个进程对相同文件映射共享
MAP_PRIVATE 多个进程对相同文件映射不共享
代码演示如下:
#include "./common/head.h"
/*功能:
*用mmap操作文件
*/
int main()
{
int fd;
if( (fd = open("hello.txt", O_RDWR)) < 0 ){
perror("open");
exit(1);
}
//原型:void *mmap(void *addr, size_t length, int prot, int flag, int fd, off_t offset);
//返回值void *可以根据实际需要,转换成任意类型的指针
char *p = mmap(NULL, 6, PROT_WRITE, MAP_SHARED, fd, 0); //hello.txt文件的length=6
//前3个字符改为ABC
p[0] = 'A';
p[1] = 'B';
p[3] = 'C';
//第2-4个字符改为3210,注意大小端问题
((int *)((char *)p + 1))[0] = 0x33323130; //跳过第1个字符,再转成int *类型,一次操作4个字符
munmap(p, 6);
return 0;
}