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. PHP中发送邮件的几种方法总结

    1. 使用 mail() 函数 没什么好讲的,就是使用系统自带的smtp系统来发送,一般是使用sendmail来发.这个按照各个系统不同而定.使用参考手册. 2. 使用管道的形式 昨天刚测试成功,使用 ...

  2. Bash 小知识点

    变量定义的时候=两边不能有空格,例如: a='Hello World' 如果变量和其它字符相连,可以用{}把变量引起来,这样就可以和相连的字符隔离 除了在变量赋值和在FOR循环语句头中,BASH中的变 ...

  3. 手把手VirtualBox虚拟机下安装rhel6.4 linux 64位系统详细文档

    下面演示安装的是在VirtualBox里安装rhel 6.4 linux 64位系统. 一.VirtualBOX 版本. 二.虚拟机的配置. 1.现在开始演示安装,一起从零开始.点击“新建”,创建新的 ...

  4. [2-sat]HDOJ3062 Party

    中文题 题意略 学2-sat啦啦啦 2-sat就是    矛盾的 ($x.x’$不能同时取) m对人 相互也有限制条件 取出其中n个人 也有可能是把一件东西分成 取/不取 相矛盾的两种情况 (那就要拆 ...

  5. cojs 疯狂的魔法树 疯狂的颜色序列 题解报告

    疯狂的魔法树 一个各种操作大杂烩的鬼畜数据结构题目 首先我们注意到树的形态是半随机的 我们可以树分块,对树分成若干个块 对于每个块我们维护一个add标记表示增量 维护一个vis标记表示覆盖量 注意标记 ...

  6. cojs 疯狂的粉刷匠 疯狂的斐波那契 题解报告

    疯狂的斐波那契 学习了一些奇怪的东西之后出的题目 最外层要模p是显然的,然而内层并不能模p 那么模什么呢,显然是模斐波那契的循环节 那么我们可以一层层的求出每层的斐波那契循环节 之后在从内向外用矩阵乘 ...

  7. jQuery编程基础精华01(jQuery简介,顶级对象$,jQuery对象、Dom对象,链式编程,选择器)

    jQuery简介 什么是jQuery? jQuery就是一个JavaScript函数库,没什么特别的.(开源)联想SQLHelper类 jQuery能做什么?jQuery是做什么的? jQuery本身 ...

  8. JS中用execCommand("SaveAs")保存页面兼容性问题解决方案

    开发环境:ASP.NET MVC,其他环境仅供参考. 问题描述:在开发中遇到这样的需求,保存页面,通常使用JavaScript的saveAs进行保存,各浏览器对saveAs支持,见下表. 代码一:初始 ...

  9. C++:静态成员

    3.7.1 静态数据成员对象是类的一个实例,每个对象都具有自己的数据成员.例如,学生类张三或李四都具有自己的学号,姓名和平均成绩.在实际使用时,常常还需要一些其他的数据项,比如学生人数.总成绩.平均成 ...

  10. POJ3009——Curling 2.0(DFS)

    Curling 2.0 DescriptionOn Planet MM-21, after their Olympic games this year, curling is getting popu ...