八、文件IO——存储映射

8.1 存储映射介绍

8.1.1 概念

  存储映射是一个磁盘文件与存储空间的一个缓存相映射,对缓存数据的读写就相应的完成了文件的读写。

  

  文件操作部分映射到虚拟内存的一块区域,我们对虚拟内存映射的那块区域进行读写操作,读写之后,那块区域自动同步到文件当中。

  4G空间分布:

  

  共享内存映射区就是文件映射到的内存区。

8.1.2 mmap---建立内存映射

1 #include <unistd.h>
2 #include <sys/mman.h>
3 //mmap(建立内存映射)
4 void *mmap(void *start, size_t length, int prot, int flags, int fd,off_t offsize);
  • 函数说明

    • mmap()用来将某个文件内容映射到内存中,对该内存区域的存取即是直接对该文件内容的读写。
    • 作用就是 使一个磁盘文件与存储空间中的一个缓存相映射
    • mmap 函数从缓存中获取数据,就相当于读文件中的相应字节。与其类似,将数据存入缓存,则相应字节就自动地写入文件。这样,就可以再不使用 read 和 write 的情况下执行 I/O
    • 子进程继承父进程的映射
  • 参数说明:
    • @start:指向欲对应的内存起始地址,通常设为NULL或0,代表让系统自动选定地址,对应成功后该地址会返回。
    • @length:代表将文件中多大的部分对应到内存。需要映射的字节数
    • @ prot:代表映射区域的保护方式,有下列组合:
      • PROT_EXEC   映射区域可被执行
      • PROT_READ   映射区域可被读取
      • PROT_WRITE      映射区域可被写入
      • PROT_NONE       映射区域不能访问
    • @flags:会影响映射区域的各种特性
      • MAP_FIXED:如果参数 start 所指的地址无法成功建立映射时,则放弃映射,不对地址做修正。通常不鼓励用此标志。
      • MAP_SHARED:对映射区域的写入数据会复制回文件内,而且允许其他映射该文件的进程共享。存储操作立刻修改映射文件内容
      • MAP_PRIVATE:对映射区域的写入操作会产生一个映射文件的复制,即私人的“写入时复制”(copy on write)对此区域作的任何修改都不会写回原来的文件内容。存储操作导致创建映射文件的副本,并对副本读写
      • MAP_ANONYMOUS:建立匿名映射。此时会忽略参数fd,不涉及文件,而且映射区域无法和其他进程共享。
      • MAP_DENYWRITE:只允许对映射区域的写入操作,其他对文件直接写入的操作将会被拒绝。
      • MAP_LOCKED:将映射区域锁定住,这表示该区域不会被置换(swap)。
      • 在调用mmap()时必须要指定MAP_SHARED 或MAP_PRIVATE。
    • @fd:为 open() 返回的文件描述词,代表欲映射到内存的文件。
    • @offset:为文件映射的偏移量,通常设置为0,代表从文件最前方开始对应,offset 必须是分页大小的整数倍。
  • 返回值
    • 若映射成功则返回映射区的内存起始地址,否则返回MAP_FAILED(-1),错误原因存于errno 中。
  • 错误代码
    • EBADF 参数fd 不是有效的文件描述词
    • EACCES 存取权限有误。如果是MAP_PRIVATE 情况下文件必须可读,使用 MAP_SHARED 则要有 PROT_WRITE 以及该文件要能写入。
    • EINVAL 参数start、length 或offset有一个不合法。
    • EAGAIN 文件被锁住,或是有太多内存被锁住。
    • ENOMEM 内存不足。

8.1.3 munmap---解除内存映射

1 #include <unistd.h>
2 #include <sys/mman.h>
3 //munmap(解除内存映射)
4 int munmap(void *start,size_t length);
  • 函数说明

    • munmap() 用来取消参数 start 所指的映射内存起始地址,参数length 则是欲取消的内存大小。
    • 当进程结束或利用 exec 相关函数来执行其他程序时,映射内存会自动解除,但关闭对应的文件描述符时不会解除映射。
  • 返回值
    • 如果解除映射成功则返回0,否则返回-1,错误原因存于 errno 中
  • 错误代码
    • EINVAL     参数 start或length 不合法。

8.2 例子

(1)写字符

  通过存储映射向文件中写入若干个字符。(文件中必须开辟空间供存储映射区同步,就相当于在写入的区域做一块空洞文件,然后将空洞文件映射到存储映射区)

 1 #include <sys/types.h>
 2 #include <sys/stat.h>
 3 #include <fcntl.h>
 4 #include <unistd.h>
 5 #include <string.h>
 6 #include <errno.h>
 7 #include <stdlib.h>
 8 #include <stdio.h>
 9 #include <fcntl.h>
10 #include <sys/mman.h>
11
12 int main(int argc, const char *argv[])
13 {
14     if(argc < 2) {
15         printf("usage: %s file\n", argv[0]);
16         exit(1);
17     }
18
19     int fd = open(argv[1], O_RDWR);
20     if(fd < 0){
21         perror("open error");
22         exit(1);
23     }
24
25
26     //在19个字节处写入一个0
27     lseek(fd, 19, SEEK_END);
28     write(fd, "0", 1);
29
30     char *addr;
31     //进行存储映射
32     addr = mmap(0, 20, PROT_WRITE, MAP_SHARED, fd, 0);
33     if(addr < 0) {
34         perror("mmap error");
35         exit(1);
36     }
37
38     //修改存储映射区的内容
39     int i;
40     for(i = 0; i < 20; i++)
41     {
42         *(addr + i) = ‘A‘ + i;
43     }
44     printf("write success\n");
45
46     //解除映射
47     munmap(addr, 0);
48
49     close(fd);
50
51     return 0;
52 }

  程序运行结果:

  

(2)文件的拷贝

 1 #include <sys/types.h>
 2 #include <sys/stat.h>
 3 #include <fcntl.h>
 4 #include <unistd.h>
 5 #include <string.h>
 6 #include <errno.h>
 7 #include <stdlib.h>
 8 #include <stdio.h>
 9 #include <fcntl.h>
10 #include <sys/mman.h>
11
12 int main(int argc, const char *argv[])
13 {
14     if(argc < 3) {
15         printf("usage: %s srcfile destfile\n", argv[0]);
16         exit(1);
17     }
18
19     int src_fd;
20     int dest_fd;
21
22     if((src_fd = open(argv[1], O_RDONLY)) < 0) {
23         perror("open error");
24         exit(1);
25     }
26
27     if((dest_fd = open(argv[2], O_RDWR | O_CREAT | O_TRUNC, 0777)) < 0) {
28         perror("open error");
29         exit(1);
30     }
31
32     // 定位到文件尾部,返回一个偏移量,反应文件长度
33     long len = lseek(src_fd, 0, SEEK_END);
34     printf("len: %ld\n", len);
35
36     // 在文件开始处跳过 len-1 个字节
37     lseek(dest_fd, len-1, SEEK_SET);
38     write(dest_fd, "0", 1); //创建了目标文件的空洞文件
39
40     char *src_map = mmap(0, len, PROT_READ, MAP_SHARED, src_fd, 0);
41     if(src_map < 0) {
42         perror("mmap error");
43         exit(1);
44     }
45
46     char *dest_map = mmap(0, len, PROT_WRITE, MAP_SHARED, dest_fd, 0);
47     if(dest_map < 0) {
48         perror("mmap error");
49         exit(1);
50     }
51
52     //存储映射区的复制并同步到文件中
53     memcpy(dest_map, src_map, len);
54     munmap(src_map, 0);
55     munmap(dest_map, 0);
56
57     close(src_fd);
58     close(dest_fd);
59
60     return 0;
61 }

  运行结果:

  

  

原文地址:https://www.cnblogs.com/kele-dad/p/9048712.html

时间: 2024-11-05 19:53:41

八、文件IO——存储映射的相关文章

mmap存储映射IO

mmap,munmap-- #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); int mprotect(void *addr, size_t len, int prot); int msync(void *addr, size_t length, int fla

存储映射IO

3.6.7.1.mmap函数3.6.7.2.LCD显示和IPC之共享内存3.6.7.3.存储映射IO的特点(1)共享而不是复制,减少内存操作(2)处理大文件时效率高,小文件不划算 总结:存储映射IO其实本质上就是共享内存,和进程间通信的IPC共享内存是一样的,区 别在于: 存储映射IO:是访问设备文件的说法,例如访问LCD设备,我们的进程是一个视频播放器 ,那么他需要将硬盘中的视频数据读取到内存中,然后再把内存中的数据拷贝到LCD驱动 维护的显存中去,之后硬件会自动实现视频的显示:这个是一般的流

第3章 文件I/O(7)_高级文件操作:存储映射

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

ElasticSearch入门 第八篇:存储

这是ElasticSearch 2.4 版本系列的第八篇: ElasticSearch入门 第一篇:Windows下安装ElasticSearch ElasticSearch入门 第二篇:集群配置 ElasticSearch入门 第三篇:索引 ElasticSearch入门 第四篇:使用C#添加和更新文档 ElasticSearch入门 第五篇:使用C#查询文档 ElasticSearch入门 第六篇:复合数据类型——数组,对象和嵌套 ElasticSearch入门 第七篇:分析器 Elasti

20150222 IO端口映射和IO内存映射(详解S3C24XX_GPIO驱动)

20150222 IO端口映射和IO内存映射(详解S3C24XX_GPIO驱动) 2015-02-22 李海沿 刚刚我们实现了linux系统内存的分配,读写,释放功能,下面,我们一鼓作气将IO端口映射及IO内存映射搞定,加油! (一)地址的概念 1)物理地址:CPU地址总线传来的地址,由硬件电路控制其具体含义.物理地址中很大一部分是留给内存条中的内存的,但也常被映射到其他存储器上(如显存.BIOS等).在程序指令中的虚拟地址经过段映射和页面映射后,就生成了物理地址,这个物理地址被放到CPU的地址

文件IO大纲

文件流与文件描述符的区别 a) 任何进程在运行时都默认打开3个流对象,(stdin, stdout, stderr)它们都有对应的文件描述符,其文件描述符分别为0,1,2,以后打开的文件描述符的值一般都选用未使用的最小值 b) LINUX为管理每个每个进程打开的文件,在进程的私有结构体struct task_struct(即进程PCB,由内核提供)中,对任何进程来说,都将为这个结构体专门分配管理打开文件信息的表项,用以指示当前进程打开的文件结构体,通俗点解释就是每一个进程都在内核的struct

存储映射--mmap

存储映射 使一个磁盘文件与存储空间中的一个缓冲区相映射. 当从缓冲区中取数据,就相当于读文件中的相应字节. 将数据存入缓冲区,则相应的字节就自动写入文件. 使用这种方法,首先应通知内核,将一个指定文件映射到存储区域中.这个映射工作可以通过mmap函数来实现.不通过IO.直接操作内存,效率更高. mmap函数 函数原型 #include <sys/mman.h> void *mmap(void *addr, size_t length, int prot, int flags,int fd, o

MySQL系列:innodb引擎分析之文件IO

innodb作为数据库引擎,自然少不了对文件的操作,在innodb中所有需要持久化的信息都需要文件操作,例如:表文件.重做日志文件.事务日志文件.备份归档文件等.innodb对文件IO操作可以是煞费苦心,其主要包括两方面,一个是对异步io的实现,一个是对文件操作管理和io调度的实现.在MySQL-5.6版本的innodb还加入了DIRECT IO实现.做了这么多无非是优化io操作的性能.在innodb的文件IO部分中,主要实现集中在os_file.*和fil0fil.*两个系列的文件当中,其中o

Linux下用文件IO的方式操作GPIO(/sys/class/gpio)(转)

通过sysfs方式控制GPIO,先访问/sys/class/gpio目录,向export文件写入GPIO编号,使得该GPIO的操作接口从内核空间暴露到用户空间,GPIO的操作接口包括direction和value等,direction控制GPIO方向,而value可控制GPIO输出或获得GPIO输入.文件IO方式操作GPIO,使用到了4个函数open.close.read.write. 首先,看看系统中有没有"/sys/class/gpio"这个文件夹.如果没有请在编译内核的时候加入