文件IO和标准I/O(缓冲IO)概念讲解、以及相关函数使用对比分析

文件IO和标准I/O(缓冲IO)对比分析

1 文件I/O
  • 文件I/O:文件I/O称之为不带缓存的IO(unbuffered I/O)。不带缓存指的是每个read,write都调用内核中的一个系统调用,数据直接在用户空间缓冲区和内核高速缓冲区之间复制

  • read()和write()系统调用在操作磁盘文件的时候不会直接发起磁盘访问,而是仅仅在用户空间缓冲区和内核缓冲区高速缓存之间复制数据,复制完毕,系统调用就会结束,然后就是内核自己解决数据在内核缓冲区到磁盘传递的问题

    1. 目的:使得I/O调用更加快速
    2. 与文件发生大量的数据传输的时候,尽量采用大的缓冲区数据据,以及执行更少的系统调用,可以大大提升I/O性能
    3. write调用把用户空间缓冲区的数据复制到内核缓冲区之后,由内核在把数据写入到磁盘,如果此时其它进程访问该文件,那么内核会把内核缓冲区的数据传递给该进程
    4. read系统调用从内核缓冲区读取数据的时候,会把缓冲区的数据读取大最大,读完之后,系统会把下一段的数据从磁盘都入到内核高速缓冲区
  • 文件空洞:程序的偏移量跨越了文件结尾,read调用会返回0,write确可以在文件结尾后面的任意位置写入数据,在文件结尾这后面的一部分数据空间就叫做文件空洞,然而文件空洞不会占用磁盘空间,只有在文件空洞中写入了数据之后,系统才会为之分配空间

  • open调用中,参数O_CREAT和O_EXCL一般放在一起用,O_EXCL用来判断文件是否存在,在创建文件的时候,如果文件已经存在,那么open就会报错,如果不使用O_EXCL标记,就算文件存在,open调用创建文件的时候,open调用也会成功,这就导致,一个文件从属两个进程,这样是不对的,两个文件可以以一个写,另外一个读的方式打开同一个文件,但是不能同时创建文件,所以这也是参数O_CREAT和O_EXCL放在一起使用的原因,让一个文件以独占的方式被创建,两个标志在一起属于一个原子操作,是不能被打断的

  • fcntl函数,判断文件的访问模式的时候,只读、只写、可读可写,三个常量不与文件标志位的单个bit位对应,要判断其访问模式,需要把获取的flag和O_ACCMODE相与的结果在和O_RDWR这类的标记比较
    在这里插入图片描述

  • 可以使用fcntl修改的某些文件的标志位只有,O_APPEND、O_NONBLOCK、O_NOATIME、O_ASYNV、O_DIRECT,系统忽略其它标记的修改操作

  • fcntl尤其适用的场景:

    1. 文件不是由调用进程打开,比如标准输入、输出等

    2. 文件描述符通过open以外的系统调用打开,比如socket()、pipe()

    3. fcntl使用举例:
      在这里插入图片描述


2 文件I/O缓冲(标准I/O)
  • 标准I/O是ANSI C建立的一个标准I/O模型,是一个标准函数包和stdio.h头文件中的定义,具有一定的可移植性。标准I/O库处理很多细节。例如缓存分配,以优化长度执行I/O等。标准的I/O提供了三种类型的缓存,相当于在文件I/O上又进行了一些封装

    1. 全缓存:当填满标准I/O缓存后才进行实际的I/O操作,例如磁盘块读写
    2. 行缓存:当输入或输出中遇到新的换行符时,标准I/O库执行I/O操作。
    3. 不带缓存:stderr就是了
  • 标准I/O带缓冲的原因:使用标准I/O,比如fopen,会在调用的时候创建一个标准I/O缓冲区,当达到标准I/O的准则的时候,在把标准I/O缓冲区的数据写入到内核缓冲区中,所以在使用标准I/O的时候,有用户空间缓冲区,标准I/O缓冲区,内核数据高速缓冲区这几个个缓冲区

    /**************************
    函数功能:设置标准I/O的缓冲工作模式
    返回值:The  function  setvbuf()  returns  0 on success.  It returns nonzero on
           failure (mode is invalid or the request cannot be honored).  It may set
           errno on failure.
    **************************/
    #inclde <stdio.h>
        
    int setvbuf(FILE *stream, char *buf, int mode, size_t size);
    /*参数
    stream:指代标准流,stdin、stdout、stderr
    buf:保存了开辟的标准I/O缓冲区,设置为NULL的话,系统自动在内存中开辟一个标准I/O缓冲区
    mode:标准I/O的工作模式
    	1.标准I/O不缓冲
    	2.采用行缓冲
    	3.采用全缓冲	
    size:标准I/O缓冲区大小,如果buf为NULL,size会被忽略
    */
    
    /**************************
    函数功能:强制把标准I/O缓冲区中的内容,刷新到内核缓冲区中
    返回值:Upon successful completion 0 is returned.  Otherwise, EOF  is  returned
           and errno is set to indicate the error.
    **************************/
    #include <stdio.h>
    
    int fflush(FILE *stream);
    /*参数:
    stream指代标准流指针
    */
    

3 内核高速缓冲区的控制
  • 同步I/O数据完整性:

    1. 对读操作来说:意味着被请求的文件数据已经从磁盘传递到进程
    2. 对写操作而言:文件数据已经传递到磁盘,但是某些文件元数据就算被修改了,比如文件的时间戳,如果没有写入磁盘,也满足数据完整性
  • 同步I/O文件完整性:是同步I/O数据完整性的超集,此时元数据也是考虑的因素之一,才能保证同步I/O文件完整性

  • 如果open调用指定了O_SYNC标志,那么write调用会直接把用户空间的数据直接刷新到磁盘中,而不会复制到内核缓冲区,但是尽量不使用这个标志,原因如下图:

  • 在这里插入图片描述

  • 缓冲示意图:
    在这里插入图片描述

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值