普通I/O方式的缺点

  普通I/O方式一般是通过调用read和write来实现对文件的读写,使用read和write来读写文件时,函数经过层层的调用后,才能够最终操作到文件,中间涉及到很多的函数调用过程,数据需要在不同的缓存间倒腾,效率会比较低。同样使用标准I/O(库函数fread和fwrite)也是如此,本身标准I/O就是对普通I/O的一种封装。

  那既然效率较低,为啥还要使用这种方式呢?原因在于,只有当数据量比较大时,效率的影响才会比较明显,如果数据量比较小,影响并不大,使用普通I/O方式还是非常方便的。

存储映射I/O的优点

  存储映射I/O的实质其实是共享,与IPC之间的内存共享很相似。譬如执行一个文件复制操作来说,对于普通I/O方式,首先需要将源文件中的数据取出来存放在一个应用层缓冲区中,接着再将应用层缓冲区中的数据写入到目标文件中。而对于存储映射I/O来说,由于源文件和目标文件都已经映射到了应用层的内存区域中,所以直接操作映射区来实现文件复制。

  首先非常直观的一点就是,使用存储映射I/O减少了数据间的复制操作,所以在效率上比普通I/O要高,其次上面讲了,普通I/O中间涉及到很多函数调用过程,这些都会导致普通I/O在效率上会比存储映射I/O要低。

  前面提到存储映射I/O的实质其实是共享,如何理解共享呢?其实很简单,我们知道,应用层与内核层是不能直接交互的,必须通过操作系统提供的系统调用或库函数与内核进行数据交互,包括操作硬件。通过存储映射I/O将文件直接映射到应用程序空间中的一块内存区域中,也就是映射区;直接将磁盘文件直接与映射区关联起来,不用调用read、write系统调用,直接对映射区进行读写操作即可操作磁盘上的文件,而磁盘文件中的数据也可反映到映射区中,这就是一种共享,可以认为映射区就是应用层和内核层之间的共享内存。

存储映射I/O的不足

  存储映射I/O方式并不是完美的,它所映射的文件只能是固定大小,因为文件所映射的区域已经在调用mmap函数时通过length参数指定了。另外,文件映射的内存区域的大小必须是系统页大小的整数倍,譬如映射文件的大小是96字节,假定系统页大小为4096字节,那么剩余的4000字节全部填充0,虽然可以通过映射地址访问剩余的这些字节数据,但不能在映射文件中反映出来,由此可知,使用存储映射I/O在进行大数据量操作时比较有效;对于少量数据,使用普通I/O方式更加方便。

存储映射I/O的应用场景

  由上面介绍可知,存储映射I/O在处理大量数据时效率高,对于少量数据处理不是很划算,所以通常来说,存储映射I/O会在视频图像处理方面用的比较多,譬如在第二篇内容,我们将介绍Framebuffer编程,通俗点说就是LCD编程,就会使用存储映射I/O。