44-共享文件映射

1. 文件映射

内存映射主要分两种:文件映射和匿名映射。

上一篇讲的就是文件映射,一般创建文件映射需要以下几个步骤:

1. 调用open函数打开一个文件,获得其文件描述符

2. 将文件描述符作为mmap函数的参数传入

                       

执行完以上步骤后,mmap函数会将文件映射到进程空间中,如果不需要用到文件描述符可以调用close关闭。

在创建文件映射时,可以指定MAP_PRIVATE创建私有文件映射,也可以指定MAP_SHARED创建共享文件映射,一般私有文件映射并不常用,这里我们主要讨论共享文件映射。

 

2. 多进程共享文件映射

对于共享文件映射来说,当多个进程以MAP_SHARED创建了同一文件区域的共享文件映射时,会共享相同的物理内存页,任意一个进程在映射区的修改操作都会反映到物理磁盘上的文件。

                                                                                  图1-多进程共享文件映射

 

上图是简化后的文件映射过程,实际的内存分页在物理内存中不是连续的,这点要注意区分。

共享文件映射通常由两个用途:内存映射I/O和IPC。

 

3. 内存映射I/O

当创建共享文件映射后,在映射区的所有I/O操作都会反映到物理磁盘的文件上,可以实现在不借助read和write等I/O调用的情况下来完成数据的读写,而是使用地址(指针)访问内存完成I/O操作,因此这种方式又称为内存映射I/O。

内存映射I/O的优势:

  1. 通过地址(指针)访问内存来代替read和write系统调用能简化应用程序的逻辑
  2. 通过地址(指针)访问内存比传统的I/O系统调用的性能更高。

 

4. 内存映射I/O的性能

为什么内存映射I/O的性能更高?我们先来看一下传统的I/O系统调用

                                                                                图2-传统的I/O系统调用

 

通常传统的read和write等系统调用需要两次的数据拷贝,以write调用为例。第一次用户空间和内核空间的缓冲区需要一次数据拷贝,第二次就是内核空间和打开的文件之间也需要一次数据拷贝。

而通过mmap创建共享文件映射后,用户进程可以直接对内核空间进行数据读写操作,这样就省略第一次的数据拷贝,然后内核会选择合适的时候自动更新物理磁盘上的文件。

另外,mmap还节省了内存的使用,因为使用传统的I/O系统调用需要两个内存缓冲区(用户空间和内核空间各一个),而使用mmap,用户进程和内核共享一个缓冲区(内核空间),所以从多进程的角度考虑,当有成千上万个进程对同一文件执行I/O操作,使用mmap性能会更加明显。

 

5. 内存映射I/O的优势

内存映射I/O的性能优势在于对大容量的文件重复执行随机读写操作。

想象一下,如果是顺序的方式访问一个大容量文件,内存映射I/O的性能就非常有限,甚至还可能会降低性能。

原因在于文件中的数据需要在磁盘和内核缓冲区之间传输,物理磁盘I/O操作会更加耗费性能,耗时。假设缓冲区足够大,传统的read和write系统调用能够避免大量执行I/O系统调用,那么内存映射I/O就会失去性能优势。

当然内存映射I/O也是有缺点的,对于小数据量I/O操作来说,内存映射I/O(创建映射,分页,解除映射等)实际上要比简单的read / write开销更多。

 

6. 内存映射I/O的大文件性能测试

以内存映射I/O和和系统调用write写500M文件为例,以下是测试结果:

内存映射I/O的大文件性能测试

      字节数(byte)

          内存映射I/O    

            系统调用write     

              1

              9.21s

             190s左右

            1024

              3.45s

                  3.24s

            4096

              3.10s

                  2.97s

            8192

              3.06s

                   2.93s

根据以上的测试结果可以得出:内存映射I/O在写数据量小的文件上比较占优势,而写大于1024字节的数据量上基本已经不占优势了。而系统调用write在写4096字节的数据上,性能才趋于平稳。

这里思考一下:为什么内存映射I/O和系统调用write在读写1字节时,差距是如此之大?

由于代码较多,我就不直接贴出来了,下载链接:https://download.csdn.net/download/qq_35733751/10702361

7. 使用共享文件映射的IPC

使用共享文件映射的进程间通信(IPC)和System V共享内存的原理是比较类似的,区别在于共享文件映射的修改操作会反映到物理磁盘上的文件,这种特性对于既要在进程间共享数据,又要把数据持久化存储到磁盘上的情况来说是非常有用的。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值