如果要把数据结构写到文件里,并且反复编辑这个文件,可能需要反复设置偏移量并进行读写操作。如果文件需要并发操作就更麻烦了。
一个简单的办法就是用mmap函数吧文件的一个区域映射到一块内存上,把文件读写转化为内存操作,对内存的修改能自动反映到文件上。
如果文件权限允许,mmap还可以实现文件的共享操作。
大致步骤
1 头文件
- sys/mman.h
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);
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博客 ” ,链接:http://blog.itpub.net/26239116/viewspace-2120888/,如需转载,请注明出处,否则将追究法律责任。
转载于:http://blog.itpub.net/26239116/viewspace-2120888/