如果要把数据结构写到文件里,并且反复编辑这个文件,可能需要反复设置偏移量并进行读写操作。如果文件需要并发操作就更麻烦了。
一个简单的办法就是用mmap函数吧文件的一个区域映射到一块内存上,把文件读写转化为内存操作,对内存的修改能自动反映到文件上。
如果文件权限允许,mmap还可以实现文件的共享操作。
大致步骤
1 头文件
2 打开文件
-
int fd = open(fname, O_RDWR);
3 将文件的一个区域映射到内存里
-
test* p1 = mmap(NULL, sizeof(test), PROT_WRITE, MAP_SHARED, fd, 0);
4 操作内存
-
memcpy(p1, &t1, sizeof(test));
5 释放map
-
munmap(p1, sizeof(test));
打开文件和释放mmap都比较简单。重点在于映射这步
-
void *mmap(void *addr, size_t length, int prot, int flags, int fd, off_t offset);
-
void *mmap64(void *addr, size_t length, int prot, int flags, int fd, off64_t offset);
参数:
addr 手工指定映射到的地址,如果传入NULL,则自动分配地址。
length 映射的长度
prot 指定希望如何保护映射到的内存。如PROT_EXEC,PROT_READ,PROT_WRITE,字面意思都很好理解。
flags 设置是否是共享内存,对内存的操作是否被其它进程看到。如MAP_SHARED,MAP_PRIVATE。
fd 文件描述符
offset 映射的文件偏移量。只能是pagesize的整数倍。pagesize可以通过sysconf(_SC_PAGESIZE)得到
解除映射
解除映射的时候需要注意的是不能再调用free了。
-
int munmap(void *addr, size_t length);
完整例子
-
#include <stdio.h>
-
#include <stdlib.h>
-
#include <sys/mman.h>
-
#include <string.h>
-
#include <errno.h>
-
#include <unistd.h>
-
#include <fcntl.h>
-
-
typedef struct st_test
-
{
-
char c[10];
-
int i;
-
long l;
-
} test;
-
-
int main()
-
{
-
uint sz = sizeof(test);
-
printf("size = %d\n", sz);
-
char fname[10] = "testfile";
-
int fd = open(fname, O_RDWR);
-
char buf[BUFSIZ];
-
memset(buf, 'a', BUFSIZ);
-
write(fd, buf, BUFSIZ);
-
puts("mmap");
-
test* p1 = mmap(NULL, sizeof(test), PROT_WRITE, MAP_SHARED, fd, 0);
-
if(p1 == MAP_FAILED)
-
{
-
printf("mmap: %s\n", strerror(errno));
-
exit(1);
-
}
-
test* p2 = mmap(NULL, sizeof(test), PROT_WRITE, MAP_SHARED, fd, 4096);
-
if(p2 == MAP_FAILED)
-
{
-
printf("mmap: %s\n", strerror(errno));
-
exit(1);
-
}
-
-
// printf("%d\n", sysconf(_SC_PAGESIZE));
-
printf("%c\n", (char*)p2);
-
test t1;
-
t1.i = 10;
-
strcpy(t1.c, "aaaa");
-
t1.l = 10000;
-
test t2;
-
t2.i = 20;
-
strcpy(t2.c, "bbbb");
-
t2.l = 20000;
-
-
getchar();
-
puts("memcpy p1");
-
memcpy(p1, &t1, sz);
-
puts("memcpy p2");
-
memcpy(p2, &t2, sz);
-
-
-
printf("%d %s %d\n", p1->i, p1->c, p1->l);
-
printf("%d %s %d\n", p2->i, p2->c, p2->l);
-
getchar();
-
msync(p1, sz, MS_SYNC);
-
msync(p2, sz, MS_SYNC);
-
-
munmap(p1, sz);
-
munmap(p2, sz);
-
-
return 0;
-
}
运行效果
[root@server2 mmap]# dmesg >testfile (创建一个大点的文件)
[root@server2 mmap]# ./a
size = 24
mmap
memcpy p1
memcpy p2
10 aaaa 10000
20 bbbb 20000
来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/26239116/viewspace-2120888/
,如需转载,请注明出处,否则将追究法律责任。