mmap UNIX 提供了一个有用的功能以运行程序共享内存。mmap(内存映射)函数的作用是建立一段可以被两个或更多个程序读写的内存。一个程序对它所做出的修改可以被其他程序看见。 这
mmap
UNIX 提供了一个有用的功能以运行程序共享内存。mmap(内存映射)函数的作用是建立一段可以被两个或更多个程序读写的内存。一个程序对它所做出的修改可以被其他程序看见。
这一功能还可以用在文件的处理上。你可以使某个磁盘文件的全部内容看起来就像是内存中的一个数组。如果文件由记录组成,而这些记录又能够C语言中的结构来描述的话,你就可以通过访问结构数组来更新文件的内容了。
mmap 函数创建一个指向一段内存区域的指针,该内存区域与可以通过一个打开的文件描述符访问的文件的内容相关联。
void* mmap(void* addr, size_t len, int prot, int flags, int fildes, off_t off);
addr
通过 addr 参数来请求使用某个特定的内存地址。如果值为0,结果指针就将自动分配。
len
可以访问的数据量(内存段的长度)。
prot
用于设置内存段的访问权限,是下列常数值的按位 OR 结果。
- PROT_READ 允许读该内存段。
- PROT_WRITE 允许写该内存段。
- PROT_EXEC 允许执行该内存段。
- PROT_NONE 该内存段不能被访问。
flags
- MAP_PRIVATE 内存段是私有的,对它的修改只对本进程有效。
- MAP_SHARED 把对该内存段的修改保存到磁盘文件中。
- MAP_FIXED 该内存段必须位于 addr 指定的地址处。
fildes
打开的文件描述符。
off_t off
改变经共享内存段访问的文件中数据的起始偏移地址。
msync
把在该内存段的某个部分或者整段中的修改写回到被映射的文件中(或者从被映射文件里读出)。
int msync(void* addr, size_t len, int flags);
内存段需要修改的部分作为参数传递过来的起始地址addr和长度len确定。
flags 参数控制着执行修改的具体方式:
- MS_ASYNC 采用异步写方式
- MS_SYNC采用同步写方式
- MS_INVALIDATE 从文件中读回数据
munmap
释放内存段。
int munmap(void* addr, size_t len);typedef struct{
int integer;
char string[24];
} RECORD;
int main()
{
RECORD record, *mapped;
int i, f;
FILE *fp;
fp = fopen("records.dat", "w+");
for(i = 0; i < NRECORDS; i++)
{
record.integer = i;
sprintf(record.string, "RECORD-%d", i);
fwrite(&record, sizeof(record), 1, fp);
}
fclose(fp);
// exit(0);
fopen("records.dat", "r+");
fseek(fp, 43*sizeof(record), SEEK_SET);
fread(&record, sizeof(record), 1, fp);
record.integer = 143;
sprintf(record.string, "RECORD-%d", record.integer);
fseek(fp, 43*sizeof(record), SEEK_SET);
fwrite(&record, sizeof(record), 1, fp);
fclose(fp);
f = open("records.dat", O_RDWR);
mapped = (RECORD*)mmap(0, NRECORDS*sizeof(record), PROT_READ | PROT_WRITE, MAP_SHARED, f, 0);
mapped[43].integer = 243;
sprintf(mapped[43].string, "RECORD-%d", mapped[43].integer);
msync((void*)mapped, NRECORDS*sizeof(record), MS_ASYNC);
munmap((void*)mapped, NRECORDS*sizeof(record));
close(f);
exit(0);
}