https://www.ibm.com/developerworks/cn/linux/l-cn-directio/

对于传统的操作系统来说,普通的 I/O 操作一般会被内核缓存,这种 I/O 被称作缓存 I/O。本文所介绍的文件访问机制不经过操作系统内核的缓存,数据直接在磁盘和应用程序地址空间进行传输,所以该文件访问的机制称作为直接 I/O。Linux 中就提供了这样一种文件访问机制,对于那种将 I/O 缓存存放在用户地址空间的应用程序来说,直接 I/O 是一种非常高效的手段。本文将基于 2.6.18 版本的内核来讨论 Linux 中直接 I/O 的技术的设计与实现。

什么是缓存 I/O (Buffered I/O)

缓存 I/O 又被称作标准 I/O,大多数文件系统的默认 I/O 操作都是缓存 I/O。在 Linux 的缓存 I/O 机制中,操作系统会将 I/O 的数据缓存在文件系统的页缓存( page cache )中,也就是说,数据会先被拷贝到操作系统内核的缓冲区中,然后才会从操作系统内核的缓冲区拷贝到应用程序的地址空间。缓存 I/O 有以下这些优点:

  • 缓存 I/O 使用了操作系统内核缓冲区,在一定程度上分离了应用程序空间和实际的物理设备。
  • 缓存 I/O 可以减少读盘的次数,从而提高性能。

当应用程序尝试读取某块数据的时候,如果这块数据已经存放在了页缓存中,那么这块数据就可以立即返回给应用程序,而不需要经过实际的物理读盘操作。当然,如果数据在应用程序读取之前并未被存放在页缓存中,那么就需要先将数据从磁盘读到页缓存中去。对于写操作来说,应用程序也会将数据先写到页缓存中去,数据是否被立即写到磁盘上去取决于应用程序所采用的写操作机制:如果用户采用的是同步写机制( synchronous writes ), 那么数据会立即被写回到磁盘上,应用程序会一直等到数据被写完为止;如果用户采用的是延迟写机制( deferred writes ),那么应用程序就完全不需要等到数据全部被写回到磁盘,数据只要被写到页缓存中去就可以了。在延迟写机制的情况下,操作系统会定期地将放在页缓存中的数据刷到磁盘上。与异步写机制( asynchronous writes )不同的是,延迟写机制在数据完全写到磁盘上的时候不会通知应用程序,而异步写机制在数据完全写到磁盘上的时候是会返回给应用程序的。所以延迟写机制本身是存在数据丢失的风险的,而异步写机制则不会有这方面的担心。

缓存 I/O 的缺点

在缓存 I/O 机制中,DMA 方式可以将数据直接从磁盘读到页缓存中,或者将数据从页缓存直接写回到磁盘上,而不能直接在应用程序地址空间和磁盘之间进行数据传输,这样的话,数据在传输过程中需要在应用程序地址空间和页缓存之间进行多次数据拷贝操作,这些数据拷贝操作所带来的 CPU 以及内存开销是非常大的。

对于某些特殊的应用程序来说,避开操作系统内核缓冲区而直接在应用程序地址空间和磁盘之间传输数据会比使用操作系统内核缓冲区获取更好的性能,下边这一小节中提到的自缓存应用程序就是其中的一种。

自缓存应用程序( self-caching applications)

对于某些应用程序来说,它会有它自己的数据缓存机制,比如,它会将数据缓存在应用程序地址空间,这类应用程序完全不需要使用操作系统内核中的高速缓冲存储器,这类应用程序就被称作是自缓存应用程序( self-caching applications )。数据库管理系统是这类应用程序的一个代表。自缓存应用程序倾向于使用数据的逻辑表达方式,而非物理表达方式;当系统内存较低的时候,自缓存应用程序会让这种数据的逻辑缓存被换出,而并非是磁盘上实际的数据被换出。自缓存应用程序对要操作的数据的语义了如指掌,所以它可以采用更加高效的缓存替换算法。自缓存应用程序有可能会在多台主机之间共享一块内存,那么自缓存应用程序就需要提供一种能够有效地将用户地址空间的缓存数据置为无效的机制,从而确保应用程序地址空间缓存数据的一致性。

对于自缓存应用程序来说,缓存 I/O 明显不是一个好的选择。由此引出我们这篇文章着重要介绍的 Linux 中的直接 I/O 技术。Linux 中的直接 I/O 技术非常适用于自缓存这类应用程序,该技术省略掉缓存 I/O 技术中操作系统内核缓冲区的使用,数据直接在应用程序地址空间和磁盘之间进行传输,从而使得自缓存应用程序可以省略掉复杂的系统级别的缓存结构,而执行程序自己定义的数据读写管理,从而降低系统级别的管理对应用程序访问数据的影响。在下面一节中,我们会着重介绍 Linux 中提供的直接 I/O 机制的设计与实现,该机制为自缓存应用程序提供了很好的支持。

直接 I/O 技术的特点

直接 I/O 的优点

直接 I/O 最主要的优点就是通过减少操作系统内核缓冲区和应用程序地址空间的数据拷贝次数,降低了对文件读取和写入时所带来的 CPU 的使用以及内存带宽的占用。这对于某些特殊的应用程序,比如自缓存应用程序来说,不失为一种好的选择。如果要传输的数据量很大,使用直接 I/O 的方式进行数据传输,而不需要操作系统内核地址空间拷贝数据操作的参与,这将会大大提高性能。

直接 I/O 潜在可能存在的问题

直接 I/O 并不一定总能提供令人满意的性能上的飞跃。设置直接 I/O 的开销非常大,而直接 I/O 又不能提供缓存 I/O 的优势。缓存 I/O 的读操作可以从高速缓冲存储器中获取数据,而直接 I/O 的读数据操作会造成磁盘的同步读,这会带来性能上的差异 , 并且导致进程需要较长的时间才能执行完;对于写数据操作来说,使用直接 I/O 需要 write() 系统调用同步执行,否则应用程序将会不知道什么时候才能够再次使用它的 I/O 缓冲区。与直接 I/O 读操作类似的是,直接 I/O 写操作也会导致应用程序关闭缓慢。所以,应用程序使用直接 I/O 进行数据传输的时候通常会和使用异步 I/O 结合使用。

 

总结

Linux 中的直接 I/O 访问文件方式可以减少 CPU 的使用率以及内存带宽的占用,但是直接 I/O 有时候也会对性能产生负面影响。所以在使用直接 I/O 之前一定要对应用程序有一个很清醒的认识,只有在确定了设置缓冲 I/O 的开销非常巨大的情况下,才考虑使用直接 I/O。直接 I/O 经常需要跟异步 I/O 结合起来使用,本文对异步 I/O 没有作详细介绍,有兴趣的读者可以参看 Linux 2.6 中相关的文档介绍。

Linux 中直接 I/O 机制的介绍的更多相关文章

  1. I/O 机制的介绍(Linux 中直接 I/O 机制的介绍)

    IO连接的建立方式 1.缓存IO.流式IO: 2.映射IO.块式IO: 3.直接IO. IO的方式: 同步.异步.定时刷新: MMAP与内核空间 mmap使用共享用户空间与内核空间实现: 直接 I/O ...

  2. 解析Linux中的VFS文件系统机制

    转载:原文地址https://www.ibm.com/developerworks/cn/linux/l-vfs/ 1. 摘要 本文阐述 Linux 中的文件系统部分,源代码来自基于 IA32 的 2 ...

  3. Linux中三种SCSI target的介绍之各个target的优劣

    版权声明:本文为博主原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明. 本文链接:https://blog.csdn.net/scaleqiao/article/deta ...

  4. 【Linux】Linux中Swap与Memory内存简单介绍

    背景介绍 对于Linux来说,其在服务器市场的使用已经占据了绝对的霸主地位,不可动摇.Linux的各种设计思想和使用也被传承(当然不乏各种黑Linux,而且黑的漂亮).Linux的很多独特的设计,对性 ...

  5. [svc]Linux中Swap与Memory内存简单介绍

    swap区域是干嘛的 cpu 内存(不常用到的进程swap区) 磁盘 当内存没有可用的,就必须要把内存中不经常运行的程序给踢出去.但是踢到哪里去,这时候swap就出现了. 背景介绍 对于Linux来说 ...

  6. Linux中Swap与Memory内存简单介绍

    1.背景介绍   这篇文章介绍一下Linux中swap与memory.对于memory没什么可说的就是机器的物理内存,读写速度低于cpu一个量级,但是高于磁盘不止一个量级.所以,程序和数据如果在内存的 ...

  7. Linux中三种SCSI target的介绍之STGT

    版权声明:本文为博主原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明. 本文链接:https://blog.csdn.net/scaleqiao/article/deta ...

  8. Linux中Swap与Memory内存简单介绍 (转)

    https://blog.csdn.net/zwan0518/article/details/12059213 一.背景介绍 对于Linux来说,其在服务器市场的使用已经占据了绝对的霸主地位,不可动摇 ...

  9. 在linux中实现多网卡的绑定 介绍常见的7种Bond模式

    网卡bond是通过把多张网卡绑定为一个逻辑网卡,实现本地网卡的冗余,带宽扩容和负载均衡.在应用部署中是一种常用的技术,我们公司基本所有的项目相关服务器都做了bond,这里总结整理,以便待查. bond ...

随机推荐

  1. Palindrome Partitioning II

    Given a string s, partition s such that every substring of the partition is a palindrome. Return the ...

  2. 使用git代替FTP部署代码到服务器的例子

    这篇文章主要介绍了使用git代替FTP部署代码到服务器的例子,这种方法可以节省流量.节省时间,需要的朋友可以参考下 本地开发完成后,通常会在服务器上部署,有人会使用ftp,有人会使用scp, ftp和 ...

  3. java生成二维码的三个工具

    1.  使用SwetakeQRCode在Java项目中生成二维码 http://swetake.com/qr/ 下载地址 或着http://sourceforge.jp/projects/qrcode ...

  4. 解决 Ubuntu 开机 Waiting for 60 seconds more for network configuration

    sudo vim /etc/network/interfaces, 将该文件的内容修改为如下:(也就是说删掉其他的什么auto eth0.auto wlan0) auto lo iface lo in ...

  5. FWT 学习总结

    我理解的FWT是在二元运算意义下的卷积 目前比较熟练掌握的集合对称差卷积 对于子集卷积和集合并卷积掌握不是很熟练(挖坑ing) 那么就先来谈一谈集合对称差卷积吧 所谓集合对称差卷积 就是h(i)=si ...

  6. lintcode:合并排序数组

    题目: 合并排序数组 合并两个排序的整数数组A和B变成一个新的数组. 样例 给出A=[1,2,3,4],B=[2,4,5,6],返回 [1,2,2,3,4,4,5,6] 挑战 你能否优化你的算法,如果 ...

  7. 什么是hibernate?

    一.什么是hibernate框架?1.通过数据库保存java运行时产生的对象和恢复对象,其实就是实现java对象与关系数据库记录的映射关系称为ORM(Object Relation Mapping), ...

  8. C++:类的组合

    在类中定义的数据成员一般都是基本数据类型或服复合数据类型.但是还可以根据需要使用 其他类的对象作为正在声明的数据成员.复杂的对象还可以有比较简单的对象一某种方式组合 而成,复杂对象和组成它的简单对象之 ...

  9. 【c++】中文设置

    #include <iostream> #include <string> #include<locale> using namespace std; ; int ...

  10. UVa 1473 - Dome of Circus 三分

    把所有的点都映射到XOZ这个平面的第一象限内,则这个三维问题可以转化二维问题: 求一条直线,使所有点在这条直线的下方,直线与X轴和Z轴围成的三角形旋转形成的圆锥体积最小. 这样转化之后可以看出直线的临 ...