前面有一篇文章 内存映射文件 给出了windows环境下,内存映射文件的例子。其实在Linux环境下,针对C语言也有相应的内存映射函数。使用内存映射函数可以提高文件读写的速度,在Linux环境下,利用mmap函数可以将指定的文件映射到内存区域中,通过对该内存区域的操作即可以实现对该文件的操作。
mmap函数的调用格式如下:
#include<sys/mman.h>
void *mmap(void *addr,size_t length,int prot,int flags, int fd,off_t offset);
该函数如果调用成功则返回文件映射区间的实际地址,否则返回MAP_FAILED(-1)。
其中,参数addr指定内存映射区域的起始位置,通常将其值设置为0,代表让系统自动选定地址,对应成功后该地址会返回;length表示映射的字节数;port表示映射区域的保护方式,有四种类型,PORT_READ、PORT_WRITE、PORT_EXEC、PORT_NONE分别表示映射区间可读、可写、可执行、不可访问;flags标识影响映射区间的相应属性,有6个取值,分别为MAP_FIXED、MAP_SHARED、MAP_PRIVATE、MAP_ANONYMOUS、MAP_DENYWRITE、MAP_LOCKED;fd标识被映射的文件描述符,该值通常是open函数的返回值;offset标识映射字节在文件中的偏移量。
下面给出一个例子,使用mmap将etc/passwd文件映射到内存区域,然后进行相应的输出操作。
#include<sys/type.h>
#include<sys/stat.h>
#include<stdio.h>
#include<fcntl.h>
#include<unistd.h>
#include<sys/mman.h>
int main()
{
int fd;
void *start;
struct stat sb;
fd=open("/etc/passwd",O_RDONLY);
fstat(fd,&sb);
start=mmap(NULL,sb.st_size,PORT_READ,MAP_PRIVATE,fd,0);
if(start==MAP_FAILED)
return 0;
printf("%s",start);
munmap(start,sb.st_size);//解除映射
close(fd);
}
编译执行结果如下:
wiki百科下面也有一个很好的例子。
#include <sys/types.h>
#include <sys/mman.h>
#include <err.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
/* Does not work on OS X, as you can't mmap over /dev/zero */
int main(void)
{
const char str1[] = "string 1";
const char str2[] = "string 2";
int parpid = getpid(), childpid;
int fd = -1;
char *anon, *zero;
if ((fd = open("/dev/zero", O_RDWR, 0)) == -1)
err(1, "open");
anon = (char*)mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_ANON|MAP_SHARED, -1, 0);
zero = (char*)mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_FILE|MAP_SHARED, fd, 0);
if (anon == MAP_FAILED || zero == MAP_FAILED)
errx(1, "either mmap");
strcpy(anon, str1);
strcpy(zero, str1);
printf("PID %d:\tanonymous %s, zero-backed %s\n", parpid, anon, zero);
switch ((childpid = fork())) {
case -1:
err(1, "fork");
/* NOTREACHED */
case 0:
childpid = getpid();
printf("PID %d:\tanonymous %s, zero-backed %s\n", childpid, anon, zero);
sleep(3);
printf("PID %d:\tanonymous %s, zero-backed %s\n", childpid, anon, zero);
munmap(anon, 4096);
munmap(zero, 4096);
close(fd);
return EXIT_SUCCESS;
}
sleep(2);
strcpy(anon, str2);
strcpy(zero, str2);
printf("PID %d:\tanonymous %s, zero-backed %s\n", parpid, anon, zero);
munmap(anon, 4096);
munmap(zero, 4096);
close(fd);
return EXIT_SUCCESS;
}
tech上有篇文章也是介绍mmap,写得也不错
http://linux.about.com/library/cmd/blcmdl2_mmap.htm
参考
https://en.wikipedia.org/wiki/Mmap
http://linux.about.com/library/cmd/blcmdl2_mmap.htm
http://baike.baidu.com/link?url=yMI8iz1KHFR0CPujxSdFFCWUykvd0QaWJcKteTaaqIeTJEcSdIkSs3Rd-9wVsE6xIvYJc7monFiXT8qHwqlrw_