--关于write()和fsync()  

----------------------------转载

write

ssize_t write(int fd, const void *buf, size_t count);

将数据写到文件中. 注意, 如果文件是保存在硬盘中, write() 函数调用返回之后, 并不表示数据已经写入到硬盘中, 这时如果掉电, 数据可能会丢失.

fsync

int fsync(int fd);

程序调用本函数, 通知内核把数据写到硬盘(file)中. 比如, 你开发一个数据库软件, 就需要这样的函数, 否则掉电或者系统崩溃时便会丢失数据.

如果你的程序不调用 fsync(), Linux 内核也会自动在”合适”的时候将你的数据真正写入到硬盘(类似调用 fsync), 最长的延时默认是 30 秒.

阻塞

阻塞是 IO 的精华所在, 不管是文件 IO 还是网络 IO, 只有真正了理解了 IO 阻塞, 才能做出所谓在高并发高性能软件(服务器).

当 fsync() 和 write() 同一个 fd 时, write() 必然阻塞. 当系统 IO 非常繁忙时, fsync() 可能会阻塞, 即使系统 IO 不繁忙, fsync() 也会因为数据量大而慢.

注: 许多 Linux 系统函数如 read(), write() 等, 粗看起来很简单, 也很容易用. 正如所有的事情一样, 要做到精致肯定不简单. 当你脱离初级的学习阶段, 要写真正生产环境的软件时, 这些”简单”的函数就大有门道了. 你需要不断的阅读它们的手册, 了解每一个参数, 每一个返回值, 同时还要阅读和试验在各种条件和环境下这些函数的表现, 这样, 才有可能做出真正的软件.

关于write()和fsync()

楼主password636(亮)2006-03-02 18:08:38 在 Linux/Unix社区 / 程序开发区 提问

关于linux系统调用write()   
  调用一次write()完毕,是不是已经写到磁盘上了?   
  是不是调用一次write(),就是一次写请求,不管写多少个字符进去,调用完都已经通过缓冲区写到磁盘上了?   
  那么fsync()这个函数是不是指将缓冲区的写到磁盘上,如果是,write完再fsync是不是多此一举?   
  我想实现的是可以先创建一个文件,然后写一些东西到该文件的缓冲区,再调用fsync()写入磁盘,请问如何实现?   
  问题点数:10、回复次数:7Top

1 楼morpheus1977()回复于 2006-03-03 22:07:46 得分 0

write()   是不带缓存的。   应该不用吧。Top

2 楼tb01412(tb)回复于 2006-03-03 22:49:08 得分 0

所谓write不带缓存是指不在C库中缓存,只要应用层调用write,就直接发出write系统调用,而内核中的write块设备都是有缓存的,所以就需要fsync将磁盘高速缓冲中的数据立刻写入磁盘中去!!!!!Top

3 楼password636(亮)回复于 2006-03-04 12:32:50 得分 0

但是为什么我write()完后,用stat()输出st_size,就是写入的个数呢?要是有缓存,应该是0啊?Top

4 楼tb01412(tb)回复于 2006-03-04 13:11:31 得分 10

呵呵,当你用write之后,内核就响应write系统调用,然后向高速磁盘缓冲块写入数据,之后,你如果用stat,或者read时,系统首先会在高速缓冲块中去查看相应的数据是否在块中,如果不是,然后再调用磁盘驱动加载磁盘数据到高速缓冲块中,然后再由高速缓冲块中返回你要的数据!!!!!这就是你用stat()输出st_size,就是写入的个数的原因!!!!!   
  系统会在合适的时机再向真正的硬件写入高速缓冲块中的数据,也可以用fsync强制把高速缓冲块中的相应数据写入磁盘!!!!!!!Top

5 楼password636(亮)回复于 2006-03-05 18:31:56 得分 0

如何能证明fsync()是强制从缓存写到磁盘上的?   
  我开始想证明fsync()是这样打算的,用open()创建一个文件,用write()写,然后用stat()获得一个size,之后调用fsync(),调用完后再用stat()获得一次size,开始由于对stat()的不理解,觉得stat()是从磁盘上读大小,第一次读应该是0,第二次即fsync()后读应该是write()进去的大小,可现在知道了stat()和read()都是从缓存中获得数据,那么有没有其他的办法在write()后fsync()前获得文件在磁盘上的大小?如果获得不了,那有什么办法能证明fsync()是从缓存强制写到磁盘上的?Top

6 楼tb01412(tb)回复于 2006-03-06 13:05:56 得分 0

如果只想证明fsync()是从缓存强制写到磁盘上的话,很简单:   
  使用U盘,你先向上面写入大量的数据(比如几十M),接着程序退出,然后马上拔出U盘(不要用umount),之后再将U盘插入,mount上去,然后再读出原来的文件内容,估计文件最后的内容不再是你原来写入的内容了!!!!   
    
  还有一种办法:   
  不通过磁盘缓冲读取数据,比如你想读sda1上的文件数据,直接用open("/dev/sda1"),而不再用实际文件目录的方式来操作,不过这样你需要自己去解析相应文件系统在磁盘上的物理组织格式才行Top

7 楼fgmIsdn()回复于 2006-03-09 15:37:43 得分 0

缓冲区有多个层次,OS内核肯定有,驱动程序也可能有,而且现在流行的硬盘驱动器上也有。   
  fsync()一般不要使用,立即写入硬盘磁介质上,会产生很多次写入动作,有损硬盘寿命,硬盘的性能也会收到影响。   
    
  硬盘涉及到比较复杂的技术。   
  目前IDE硬盘从2MB缓存向8MB缓存过渡,大容量有16MB的。

关于write()和fsync()的更多相关文章

  1. linux 同步IO: sync msync、fsync、fdatasync与 fflush

    最近阅读leveldb源码,作为一个保证可靠性的kv数据库其数据与磁盘的交互可谓是极其关键,其中涉及到了不少内存和磁盘同步的操作和策略.为了加深理解,从网上整理了linux池畔同步IO相关的函数,这里 ...

  2. Linux就这个范儿 第15章 七种武器 linux 同步IO: sync、fsync与fdatasync Linux中的内存大页面huge page/large page David Cutler Linux读写内存数据的三种方式

    Linux就这个范儿 第15章 七种武器  linux 同步IO: sync.fsync与fdatasync   Linux中的内存大页面huge page/large page  David Cut ...

  3. Linux系统调用---同步IO: sync、fsync与fdatasync【转】

    转自:http://blog.csdn.net/cywosp/article/details/8767327 [-] 1  write不够需要fsync 2 fsync的性能问题与fdatasync ...

  4. 同步内核缓冲区sync、fsync和fdatasync函数

    转自http://www.2cto.com/os/201409/339460.html 同步内核缓冲区 1.缓冲区简介 人生三大错觉之一:在调用函数write()时,我们认为该函数一旦返回,数据便已经 ...

  5. 文件I/O之sync、fsync和fdatasync函数

    传统的UNIX实现在内核中设有缓冲区高速缓存或页面高速缓存,大多数磁盘I/O都通过缓冲进行.当将数据写入文件时,内核通常先将数据复制到其中一个缓冲区中,如果 该缓冲区尚未写满,则并不将其排入输出队列, ...

  6. mysql strace fsync,fdatasync

    mysql> show create table y; +-------+------------------------------------------------------------ ...

  7. LINUX 文件系统JBD ----深入理解Fsync

    http://www.cnblogs.com/hustcat/p/3283955.html http://www.cnblogs.com/zengkefu/p/5639200.html http:// ...

  8. sync fsync fdatasync ---systemtap跟踪

    aa.stp: probe kernel .function ( "sys_sync" ) { printf ( "probfunc:%s fun:%s\n", ...

  9. mysql在高内存、IO利用率上的几个优化点 (sync+fsync) 猎豹移动技术博客

    http://dev.cmcm.com/archives/107 Posted on 2014年10月16日 by liuding | 7条评论 以下优化都是基于CentOS系统下的一些优化整理,有不 ...

  10. 《UNIX环境高级编程》笔记--sync、fsync和fdatasync函数

    传统的UNIX实现在内核中设有缓冲区高速缓存或页面高速缓存,大多数磁盘 I/O都通过缓冲进行.当将数据写入文件时,内核通常先将该数据复制到其中一个缓冲区中,如果该缓冲区尚未写满,则并不将其排入输出队列 ...

随机推荐

  1. Unity3D Image 组件附入图片问题

    作为新手经常会看到有个Image的组件 代码中理所当然的public 发现图片并不能附入其中, 解决办法直接 public Sprite 就可以了

  2. ArrayList源码浅析(jdk1.8)

    ArrayList的实质就是动态数组.所以可以通过下标准确的找到目标元素,因此查找的效率高.但是添加或删除元素会涉及到大量元素的位置移动,所以效率低. 一.构造方法 ArrayList提供了3个构造方 ...

  3. 在Linux安装配置Tomcat 并部署web应用 ( 三种方式 )

    系统版本:centos6.5版本 java版本:1.7 一.准备工作 1.java -version 检查是否有java环境,没有则需要去安装并配置到环境变量中. 2.下载tomcat包,下载地址:h ...

  4. 大数据Python学习大纲

    最近公司在写一个课程<大数据运维实训课>,分为4个部分,linux实训课.Python开发.hadoop基础知识和项目实战.这门课程主要针对刚从学校毕业的学生去应聘时不会像一个小白菜一样被 ...

  5. 玩玩微信公众号Java版之三:access_token及存储access_token

    微信官方参考文档:https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1421140183   基本说明: access_token是 ...

  6. JavaScript Base64加解密

    Base64加密算法是网络上最常见的用于传输8Bit字节代码的编码方式之一,大家可以查看RFC2045-RFC2049,上面有MIME的详细规范.Base64编码可用于在HTTP环境下传递较长的标识信 ...

  7. tensorflow max_pool(最大池化)应用

    1.最大池化 max pooling是CNN当中的最大值池化操作,其实用法和卷积很类似. tf.nn.max_pool(value, ksize, strides, padding, name=Non ...

  8. 【SignalR学习系列】8. SignalR Hubs Api 详解(.Net C# 客户端)

    建立一个 SignalR 连接 var hubConnection = new HubConnection("http://www.contoso.com/"); IHubProx ...

  9. 现代C++新四大名著及C++学习杂谈

    现代C++新四大名著及C++学习杂谈 翻开自己的博客,在2012年8月我曾经写过如下一篇博客, <<C++学习的方法以及四大名著>> http://www.cnblogs.co ...

  10. WMware虚拟机NAT模式配置网络设置Linux虚拟机固定IP

    一.主机配置 1.查看本机ip 2.给vmnet8设置固定IP和网段 3.根据vmnet8网段设置VMware NAT模式网段 4.点击NAT设置网关 二.启动虚拟机 网络设置如下: 这个地址值在这个 ...