关于direct io

简介:

direct io是一种不用内核缓存的io,它可以做到直接将用户空间的内存直接写入磁盘或者将磁盘数据直接读到用户空间的缓冲区,这种策略就是不用内核的缓存而使用用户自己设计的缓存,这一般在数据库系统中用到,初用linux的人在调用free命令的时候都会大吃一惊,为何文件cache占用了那么多的内存,太可怕了啊,其实这正是表明了该用户是初用户,这正是linux的风格,空闲内存闲着也是闲着,既然没有用户用,那么就用来缓存文件数据,这样可以尽量加速linux的用户感知速度,只要用户实际要用内存的时候,文件cahce肯定会让位,那么有人会问,即使文件cache会让位,那么将文件cahce换出也需要时间,其实这个问题的解决很简单,就是维持系统空闲内存在一个范围内,这就是kswap的作用,可以做一个试验,就是在系统初启动的时候,执行cp -r /etc /home/zhaoya/test/,等待,看表,足足八秒,然后执行rm -rf /home/zhaoya/test/etc/,然后再执行cp -r /etc /home/zhaoya/test/,发现只用了3秒不到,这就是文件缓存的作用,可是不管怎么说有的用户还是对文件cache不看好,其实不想用文件cache的人有两类,一类是觉得文件cache占用内存太多,另一类就是拥有自己的用户空间的cahce算法,不需要内核的cahce,这两种中,第一种是错误的想法,第二种才是正确的想法。于是linux没有提供禁用文件cache的系统调用或者/proc接口,但是却给了对于单独文件禁用cahce的方法,也就是说,如果说你想禁用cahce,那么如果你是觉得它占用内存太多,那么你就忍忍吧,好好再学学linux,系统不会让你禁用整个系统的文件cache,如果你是觉得自己有用户空间的cahce,那么你一定是对于操作特殊的文件拥有自己的策略,于是在open系统调用中提供了O_DIRECT标志,这标志表明这个文件打开后不再使用内核的cache,而是使用自己的cache,不过在某一个时间,如果你想失效系统中所有的文件cache,那么可以将3写入/proc/sys/vm/drop_cahces文件,这个可以使用sysctl来进行。

还有一个问题就是带有O_DIRECT标志打开的文件的mmap问题,通过读代码可以知道,mmap中没有判断有没有O_DIRECT标志的逻辑,并且在mmap中不管打开方式如何,都会采用文件cache的方式,因为所谓文件的mmap就是将文件的内核cache页面直接映射到用户空间的虚拟地址空间,mmap的本意就是将文件映射到用户空间,而linux中文件在内核内存中的唯一表示就是文件cache,于是mmap带有O_DIRECT标志的文件时,也会使用文件cache,但是一旦直接read或者write这些直接读写的文件,那么就会在直接读写前将已经mmap到用户空间的该文件的内核cache页面设置为脏,然后等待这些页面回写到磁盘后再开始直接io,因为不但这个文件可能同时被映射到用户空间,而且别的进程也可能打开该文件并且不带有O_DIRECT标志,如此为了不出现数据不一致的错误,O_DIRECT打开的文件在读写的时候必须是独占该文件的。具体判断是否有别的进程映射该文件的方式就是搜索该文件的mapping的优先搜索树,一旦这棵树不为空,那么就说明有进程映射这个文件,然后一个一个找到这些vma,并且根据反向映射将这些vma的页面的进程的页表置为无效。



 本文转自 dog250 51CTO博客,原文链接:http://blog.51cto.com/dog250/1273394


相关文章
|
前端开发 关系型数据库 数据库
|
测试技术 文件存储
NAS特定场景下buffered io比direct io读性能差问题的调查
最近一位NAS用户在微信上报道了NAS的性能测试报告,报告中测试数据显示buffered io读性能比direct io读要差。这显然和直观的认识不符,在内存充足的情况下,buffered io读的数据一般都在page cache中,每次读都是内存操作,其性能应该远远高于direct io,但测试.
4875 1
|
25天前
|
存储 缓存 安全
Java 中 IO 流、File文件
Java 中 IO 流、File文件
|
8天前
|
Java Unix Windows
|
3天前
|
存储 Java
java IO接口(Input)用法
【5月更文挑战第1天】Java的`java.io`包包含多种输入输出类。此示例展示了如何使用`FileInputStream`从`input.txt`读取数据。首先创建`FileInputStream`对象,接着创建一个字节数组存储读取的数据,调用`read()`方法将文件内容填充至数组。然后将字节数组转换为字符串并打印,最后关闭输入流。注意,`InputStream`是抽象类,此处使用其子类`FileInputStream`。其他子类如`ByteArrayInputStream`、`ObjectInputStream`和`BufferedInputStream`各有特定用途。
13 2
|
4天前
|
存储 Java Linux
【Java EE】 文件IO的使用以及流操作
【Java EE】 文件IO的使用以及流操作
|
5天前
|
存储 Java 测试技术
Java基础IO总结(下)
Java基础IO总结(下)
11 0
|
5天前
|
存储 Java
Java基础IO总结(上)
Java基础IO总结(上)
11 0