文件IO缓冲

出于速度和效率考虑,系统IO调用和标准C语言库函数在操作磁盘文件时会对数据进行缓冲。

1、文件IO的内核缓冲

  read和write系统调用在操作磁盘文件时不会直接发起磁盘访问,而仅是在用户空间缓冲区和内核缓冲区之间复制数据。

  write调用后会立即返回,在后续某个时刻内核才会将缓冲区中的数据写入磁盘,即系统调用和磁盘操作并不同步。如果在此期间,另一进程试图读取文件的这几个字节,那么内核将自动从缓冲区中提供这些数据,而不是从文件中读取。

  同理,对输入而言,内核从磁盘中读取数据并存储到内核缓冲区中。read调用将从该缓冲区中读取数据,直至把缓冲区读完,这时内核会将文件的下一段内容读入缓冲区(内核通常会执行预读)。

2、stdio库的缓冲

  当操作磁盘文件时,缓冲大块数据以减少系统调用,C语言函数库的IO函数正是这么做的,使用stdio库可以免于自行处理对数据的缓冲。

设置缓冲模式

  调用setvbuf函数,可以控制stdio库使用缓冲的形式。

#include <stdio.h>
int setvbuf(FILE *stream, char *buf, int mode, size_t size);成功返回0,错误返回非0

  参数stream标识要修改哪个流的缓冲。打开流后,必须在调用其它stdio函数之前调用setvbuf,setvbuf调用将影响后续在指定流上的所有stdio操作。
  参数buf和size则指定针对参数stream要使用的缓冲区的位置和大小, buf为NULL时stdio库会自动分配。
  参数mode指定了缓冲类型,可取下列值之一:

  • _IONBF
      不缓冲。每个stdio库函数将立即调用write或read,并且忽略buf和size参数。stderr默认属于这一类型,从而保证错误立即输出。
  • _IOLBF
      行缓冲。指代终端设备的流默认属于这一类型。对于输出流,在输出一个换行符时将刷新缓冲区;对于输入流,每次读取一行数据。
  • _IOFBF
      全缓冲。每次读写数据(通过read和write)的大小与缓冲区相同(即缓冲区满了才会调用write一次性写入磁盘),指代磁盘的流默认采用此模式。

无论当前采用何种缓冲模式,任何时候都可以使用fflush库函数强制刷新缓冲区到内核缓冲区。当关闭流时,也会刷新其缓冲区。

#include <stdio.h>
int fflush(FILE *stream);

3、控制文件IO的内核缓冲

  有时,我们需要强制刷新内核缓冲区数据到磁盘文件中。比如数据库等应用,需要确保继续操作前将输出真正写入磁盘。

控制内核缓冲的系统调用
  • fsync

    
    #include <unistd.h>
    
    int fsync(int fd);成功返回0,失败返回-1

      fsync系统调用将使缓冲数据和与打开文件描述符fd相关的所有元数据都刷新到磁盘上。fsync会同时传递修改的文件数据和文件元数据到磁盘,且在数据传递到磁盘完成后才会返回。

  • fdatasync

    
    #include <unistd.h>
    
    int fdatasync(int fd);成功返回0,失败返回-1

      如果修改文件并未导致文件大小发生变化,则fdatasync只会同步修改的文件数据到磁盘,而不会同步文件元数据。相比fsync会少一次IO操作。

  • sync

    
    #include <unistd.h>
    
    void sync(void);

      sync系统调用会使包含更新文件信息的所有内核缓冲区(即数据块,指针块,元数据等)刷新到磁盘上。在Linux上,sync调用会在所有数据传递到磁盘上后返回。而SUSv3标准却允许sync实现只是简单高度一下IO传递,在同步未完成前就可以返回。

  • O_SYNC标志

  调用open函数时如指定O_SYNC标志,则会使所有后续输出同步,每个write调用会自动将文件数据和元数据刷新到磁盘上。

注:采用O_SYNC标志或频繁调用fysnc、fdatasync、sync对性能的影响极大。

IO缓冲小结

这里写图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值