同步内核缓冲区

1.缓冲区简单介绍

人生三大错觉之中的一个:在调用函数write()时,我们觉得该函数一旦返回,数据便已经写到了文件里.可是这样的概念仅仅是宏观上的.实际上。操作系统实现某些文件I/O时(如磁盘文件)。为了保证I/O的效率,在内核一般会用到一片专门的区域(内存或独立的I/O地址空间)作为I/O数据缓冲区.它用在输入输出设备和CPU之间,用来缓存数据,使得低速的设备和快速的CPU可以协调工作避免低速的输入输出设备长时间占用CPU。降低系统调用,提高了CPU的工作效率.

2.不同步的write()

传统的UNIX或LINUX系统在设计时使用了内核缓冲区,设有快速缓冲区或页面快速缓冲区,大多数磁盘I/O都通过缓冲区进行.当将数据写入文件时,内核通常先将该数据拷贝到当中一个缓冲区。假设该缓冲区尚未写满。则并不将其排入输出队列,而是等待其写满或者当内核须要重用该缓冲区以便存放其它磁盘块数据时,再将该缓冲区排入输出队列;然后待其到达队首时。才进行实际的I/O操作.这样的输出方式被称为延迟写.

    当调用write()函数写出数据时,数据一旦写到该缓冲区(关键:仅仅是写到缓冲区),函数便马上返回.此时写出的数据能够用read()读回,也能够被其它进程读到,可是并不意味着它们已经被写到了外部永久存储介质上。即使调用close()关闭文件后也可能如此. 由于缓冲区的数据可能还在等待输出.

    因此。从数据被实际写到磁盘的角度来看。用write()写出的文件数据与外部存储设备并非全然同步的.不同步的时间间隔非常短,一般仅仅有几秒或十几秒,详细取决于写出的数据量和I/O数据缓冲区的状态.虽然不同步的时间间隔非常短,可是假设在此期间发生掉电或者系统崩溃,则会导致所写数据来不及写至磁盘而丢失的情况.

    注意:内核将缓冲区中的数据“写”到标准输入磁盘文件里,这里“写”不是将缓冲区中的数据移动到磁盘文件里,而是复制到磁盘文件里,也就说此时磁盘文件里还保留一份缓冲区内容的备份.如图1所看到的.做出这一设计也是有其道理的。假设写出到磁盘文件上,磁盘坏了或满了等等,总之就是无法将数据送出,假如没备份。那数据不是丢掉了.也就是说内核会等待写入磁盘动作完毕后,才放心的将备份的数据删除掉.在下文讨论的三个函数中也将涉及到这个过程.

 
图1 数据传入过程示意图


为了保证磁盘上实际文件系统与缓冲区快速缓存中内容的一致性,UNIX系统提供了sync、fsync和fdatasync三个函数.

3.sync函数

头文件:#include<unistd.h>

定义函数:void sync(void);

返回值:若成功则返回0,若出错则返回-1。同一时候设置errno以指明错误.

函数说明:

    sync负责将系统缓冲区的数据“写入”磁盘。以确保数据的一致性和同步性.注意:sync函数仅仅是将全部改动过的块缓冲区排入写队列,然后就返回。他并不等待实际I/O操作结束.所以不要觉得调用了sync函数,就觉得数据已安全的送到磁盘文件上,有可能会出现故障,可是sync函数是无法得知的.

    系统守候进程一般每隔一段时间调用一次sync函数,确保定期刷新内核的块缓存.UNIX系统中,系统守候进程update会周期性地(一般每一个30秒)调用sync函数.命令sync(1)也调用sync函数.

4.fsync函数

头文件:#include<unistd.h>

定义函数:int fsync(int filedes);

返回值:若成功则返回0。若出错则返回-1。同一时候设置errno以指明错误.

函数说明:

    与sync函数不同,fsync函数仅仅对由文件描符filedes指定的单一文件起作用,强制与描写叙述字fildes相连文件的全部改动过的数据(包含核内I/O缓冲区中的数据)传送到外部永久介质。即刷新fildes给出的文件的全部信息。而且等待写磁盘操作结束,然后返回.调用 fsync()的进程将堵塞直到设备报告传送已经完毕.这个fsync就安全点了.

    一个程序在写出数据之后。假设继续进行兴许处理之前要求确保所写数据已写到磁盘,则应当调用fsync().比如,数据库应用一般会在调用write()保存关键交易数据的同一时候也调用fsync().这样更能保证数据的安全可靠.

5.fdatasync函数

头文件:#include<unistd.h>

定义函数:int fdatasync(int filedes);

返回值:若成功则返回0。若出错则返回-1,同一时候设置errno以指明错误.

函数说明:

    fdatasync函数类似于fsync函数,但它仅仅影响文件数据部分。强制传送用户已写出的数据至物理存储设备。不包含文件本身的特征数据.这样能够适当降低文件刷新时的数据传送量.而除数据外,fdatasync还会同步更新文件的属性.

6.错误代码

EBADF:文件描写叙述符无效。或文件已关闭.

EIO : 读写的过程中错误发生 .

EROFS, EINVAL:文件所在的文件系统不支持同步.

7.fflush()与fsync()的联系

内核I/O缓冲区是由操作系统管理的空间,而流缓冲区是由标准I/O库管理的用户空间.fflush()仅仅刷新位于用户空间中的流缓冲区.fflush()返回后。仅仅保证数据已不在流缓冲区中,并不保证它们一定被写到了磁盘.此时。从流缓冲区刷新的数据可能已被写至磁盘。也可能还待在内核I/O缓冲区中.要确保流I/O写出的数据已写至磁盘,那么在调用fflush()后还应当调用fsync().

8.综述

尽管延迟写降低了磁盘读写次数,可是却降低了文件内容的更新速度,使得欲写到文件里数据在一段时间内并没有写到磁盘上。当系统发生问题时,这样的延迟可能造成文件更新内容的丢失。

同步内核缓冲区 sync、fsync和fdatasync函数的更多相关文章

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

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

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

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

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

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

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

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

  5. 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 ...

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

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

  7. 【珍藏】linux 同步IO: sync、fsync与fdatasync

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

  8. linux 同步IO: sync、fsync与fdatasync、sys_sync【转】

    本文转自:http://blog.csdn.net/cywosp/article/details/8767327 和 http://www.2cto.com/os/201204/126687.html ...

  9. linux 同步IO: sync、fsync与fdatasync

    [linux 同步IO: sync.fsync与fdatasync] 传统的UNIX实现在内核中设有缓冲区高速缓存或页面高速缓存,大多数磁盘I/O都通过缓冲进行.当将数据写入文件时,内核通常先将该数据 ...

随机推荐

  1. 基于Visual C++2013拆解世界五百强面试题--题13-找最大公共子字符串

    编程实现:找出两个字符串中最大公共子字符串,如"abccade"和"dgcadde"的最大子字符串为"cad". 如果不考虑效率的话直接比较 ...

  2. Windows平台下C++插件系统实现的几个关键技术问题及其解决思路

    根据我的实践,在Windows平台下设计并实现一个C++插件系统,需要解决几个关键技术问题.下面我谈谈需要解决的几个关键技术问题以及我想到的简单的解决思路.由于我主要专注于Windows平台C++程序 ...

  3. Noip2010提高组总结

    将Noip2010重新做了一遍,第一遍做下来居然只有290分,比当年浙江的一等线低了20分,因为各种坏习惯丢掉了许多分数,Noip时需要特别注意! T1:机器翻译 第一题直接暴力,内存足够所以不用循环 ...

  4. USACO 2001 OPEN

    第1题 绿组. 奶牛接力赛[relay] 题目描述 农夫约翰已经为一次赛跑选出了K(2≤K≤40)头牛组成了一支接力队.赛跑在农夫约翰所拥有的农场上进行,农场的编号为1到Ⅳf4≤Ⅳ< 800), ...

  5. java.lang.NoSuchMethodError: javax.persistence.OneToMany.orphanRemoval()Z

    我现在用的是hibernate3.6final,出现了下面这个异常:(当我使用@ManyToOne时,不会出现异常,而且用@ManyToMany也正常) Caused by: java.lang.No ...

  6. mac下配置cocos2d-x3.0

    今天看到3.0的正式版公布了,就马上荡下来试试3.0,以下记录下环境变量配置过程 打开用户文件夹下.bash_profile文件,配置环境 1.首先配置下android sdk,我的是在opt文件夹下 ...

  7. [置顶] P2P之我见,关于打洞的学问-------开篇

    最近忙项目,有点累,无暇顾急博客,4月份本来想写写流媒体的文章,结果回家休了两个月回深圳后,接了P2P的项目,那就开始P2P吧. P2P起源于美国大学生Shawn Fanning 写的一个分享软件Na ...

  8. 打包jar类库与使用jar类库

    翻译人员: 铁锚 翻译时间: 2013年11月17日 原文链接:  Build a Java library by using jar file 代码复用是软件开发中很重要的一个原则.将常用的函数构建 ...

  9. js常用几种类方法实现

    js定义类方法的常用几种定义 1 定义方法,方法中包含实现 function createCORSRequest() { var xhr = new XMLHttpRequest(); xhr.onl ...

  10. projecteuler之58题Spiral primes

    package com.android; public class SpiralPrimes { public static void main(String args[]) { long numPr ...