第3章 文件I/O_高级文件操作:存储映射
Posted 浅墨浓香
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了第3章 文件I/O_高级文件操作:存储映射相关的知识,希望对你有一定的参考价值。
8. 高级文件操作:存储映射
(1)概念:
存储映射是一个磁盘文件与存储空间的一个缓存相映射,对缓存数据的读写就相应的完成了文件的读写。
(2)mmap和munmap函数
头文件 |
#include<sys/types.h> #include<sys/mman.h> |
函数 |
void* mmap(void* addr, size_t length, int prot, int flags, int fd, off_t offset); int munmap(void* addr, size_t length); |
返回值 |
mmap成功时返回映射区的起始地址,munmap成功为0,两者出错均返回-1。 |
功能 |
mmap:I/O使一个磁盘文件与存储空间中的一个缓存相映射。 Munmap:解除映射。 |
参数 |
(1)addr:存储映射区的起始地址,通常设为0,让系统自动分配 (2)length:需要映射的字节数。 (3)prot:保护策略 ①PROT_READ:映射区可读;②PROT_WRITE:映射区可写; ③PROT_EXEC:映射区可执行;④PROT_NONE:映射区不可访问。 (4)flags: ①MAP_FIXED:返回地址必须等于addr,不鼓励使用 ②MAP_SHARED:存储操作立刻修改映射文件内容。 ③MAP_PRIVATE:存储操作导致创建映射文件的副本,并对副本读写。 (5)offset:映射字节在文件中的偏移量 |
备注 |
(1)mmap函数从缓存中获取数据,就相当于读文件中相应的字节。与其类似,将数据存入缓存,则相应字节就自动地写入文件。这样,就可以在不使用read和write的情况下执行I/O。 (2)子进程继承父进程的存储映射区。 |
【编程实验】存储映射实现文件写入
//file_map.c
#include <unistd.h> #include <fcntl.h> #include <stdlib.h> #include <stdio.h> #include <sys/mman.h> #include <string.h> int main(int argc, char* argv[]) { if(argc < 2){ printf("usage: %s file\\n",argv[1]); exit(1); } int fd = open(argv[1], O_RDWR | O_CREAT | O_TRUNC); if(fd < 0){ perror("open error"); exit(1); } //定位到文件尾部第26个字节的位置,并创建一个空洞文件 lseek(fd, 25, SEEK_END);//定位第26个字母Z,所在的位置 write(fd, "0", 1); //先写入一个"0",以后会被字母Z覆盖 //对文件的“空洞”区进行存储映射 char* addr = mmap(0, //映射区起始地址由系统自动分配 26, //映射的字节数 PROT_WRITE, MAP_SHARED, fd, 0); //从指定的文件偏移量处开始映射 //修改存储映射区的内容(会同步到文件中去) int i = 0; for(i=0; i<26; i++) { *(addr + i) = \'A\' + i; //往空洞区写入26个大写字母 } printf("write success\\n"); //解除映射 munmap(addr, 0); close(fd); return 0; }
【编程实验】存储映射实现文件的拷贝
//cp_map.c
#include <unistd.h> #include <stdio.h> #include <stdlib.h> #include <fcntl.h> #include <sys/mman.h> #include <string.h> int main(int argc, char* argv[]) { if(argc < 3){ printf("usage: %s srcfile, destfile\\n", argv[0]); exit(1); } int srcfd = open(argv[1], O_RDONLY); if (srcfd < 0) { perror("open error"); exit(1); } int dstfd = open(argv[2], O_RDWR | O_CREAT | O_TRUNC, 0777); if(dstfd < 0 ) { perror("open error"); exit(1); } off_t len = lseek(srcfd, 0, SEEK_END); //源文件的长度 printf("len: %ld\\n", len); //源文件映射到内存 char* addr1 = mmap(0, len, PROT_READ, MAP_SHARED, srcfd, 0); if(addr1 < 0) { perror("mmap error"); exit(1); } //在目标文件中,首先创建一个空洞文件 lseek(dstfd, len-1, SEEK_SET); write(dstfd, "0", 1); //这个0会被后面复制而来的文件内容覆盖 //目标文件映射到内存 char* addr2 = mmap(0, len, PROT_WRITE, MAP_SHARED, dstfd, 0); if(addr2 < 0) { perror("mmap error"); exit(1); } //存储映射区的复制,并同步到目标文件中 memcpy(addr2, addr1, len); //拷addr1内容拷到addr2中 printf("copy success!\\n"); //撤销映射 munmap(addr1, 0); munmap(addr2, 0); close(srcfd); close(dstfd); return 0; }
以上是关于第3章 文件I/O_高级文件操作:存储映射的主要内容,如果未能解决你的问题,请参考以下文章