涉及linux中IO编程的时候,我们总是不可避免地要跟各种各样的缓冲机制打交道,学好linux IO编程不是简单地掌握几个函数的用法就万事大吉,正确地运用IO需要对其缓冲机制全面的理解,切不可依葫芦画瓢,蒙混过关。

切入正题之前,我们先看一个简单的程序:


#include <stdio.h>
#include <errno.h>

#include <unistd.h>


#define BUFSIZE 5*1024

int
main(void){
    FILE *fp1, *fp2;
    char buf[BUFSIZE];

fp1 = fopen("src", "r");
    fp2 = fopen("des", "w");

fgets(buf, BUFSIZE, fp1);
    fputs(buf, fp2);

sleep(30);
    return 0;
}


其中src是一个只有一行的文本文件,这一行有4500个字符(即占用4.5k存储空间)。

注意到程序倒数第二行睡眠本分钟,我们在此期间查看两个相关文件,如下:

figure1. sleep函数结束之前两个文件src和des的大小

程序运行结束后,我们再次查看两个相关文件,如下:

figure2. sleep函数结束之后两个文件src和des的大小

从这个图1可以清晰地看到,fputs函数在既没有遇到换行符,也没有被强制冲洗的情况下输出了4k大小的字符,原因在于标准IO库函数自动分配的缓存区满了,自动进行了缓存区冲洗,从而导致了真正的IO操作。记住,这4k数据是由于缓冲区满了之后通过fputs函数被刷新 出去的,而剩下的字符则跟fputs没有任何关系了,它们是由于程序最后调用了return 语句,退出进程的时候系统自动刷新所有的IO流以及关闭所有打开的文件句柄的时候被刷新至内核的。

举着个例子的原因在于,很多人不明白UNIX中所谓的行缓冲、全缓冲以及无缓冲本质是什么,总是很容易跟在程序中调用的fgets函数、fread函数的读取方式相混淆,甚至跟自定义的缓冲区(如上面例子中提到的buf)相混淆。

我们要搞清楚上面例子中的那些关系,必须着重强调的一点是:用户空间中实际开辟了两个缓冲区,一个是看得见那个buf,就是我们自己手工创建的,另一个是库函数中为我们创建的4k缓冲区。

这个缓冲区是怎么来的呢?注意到这句定义文件指针的语句没有:FILE *fp;其中FILE就是一个结构体,我们打开一个文件之后就利用句柄fp与实际内存中与此文件对应的那个结构体关联起来,这个结构体大致如下(在库函数源代码文件中的libio/libio.h中定义):


struct _IO_FILE {
  int _flags;        /* High-order word is _IO_MAGIC; rest is flags. */
#define _IO_file_flags _flags

/* The following pointers correspond to the C++ streambuf protocol. */
  /* Note:  Tk uses the _IO_read_ptr and _IO_read_end fields directly. */
  char* _IO_read_ptr;    /* Current read pointer */
  char* _IO_read_end;    /* End of get area. */
  char* _IO_read_base;    /* Start of putback+get area. */
  char* _IO_write_base;    /* Start of put area. */
  char* _IO_write_ptr;    /* Current put pointer. */
  char* _IO_write_end;    /* End of put area. */
  char* _IO_buf_base;    /* Start of reserve area. */
  char* _IO_buf_end;    /* End of reserve area. */ 
  /* The following fields are used to support backing up and undo. */
  char *_IO_save_base; /* Pointer to start of non-current get area. */
  char *_IO_backup_base;  /* Pointer to first valid character of backup area */
  char *_IO_save_end; /* Pointer to end of non-current get area. */
  ... ... ...

  ... ... ...

};


我们只关心红色标识的那两行,就是这两个字符指针,指向了一个4k大小的内存缓冲区,库函数把这个缓冲区作为与内核交互数据的场所,所谓的行缓冲、全缓冲、无缓冲都是相对这块内存区域而言的,绝非我们自己定义的那个buf,也跟fgets的按行读取模式没有什么关系。
它们的关系可以简单地用一下这幅图来表示:

实际上像fgets函数这样按行读取的函数,它的按行读取指的是把数据填充到自定义的那个buf时一行一行地读,最终是通过标准IO库里面的缓冲区跟具体文件交互的。

IO编程 之 缓冲篇相关推荐

  1. Java IO篇 Java IO编程

    Java IO 一.java io 概述 1.1 相关概念 二.Java IO类库的框架 2.1 Java IO的类型 2.2 IO 类库 三.Java IO的基本用法 3.1 Java IO :字节 ...

  2. linux 带缓存的fwrite,文件IO编程之(六):基于流缓冲 fopen,fwrite,fput

    标准IO开发 前面分析的文件IO编程都是基于文件描述符的.这些都是基本的IO控制,是不带缓存的. 这里要讨论的IO操作是基于流缓冲的,它是符合ANSIC的标准IO处理. 标准IO提供流缓冲的目的是尽可 ...

  3. 【Java基础】Java IO编程:输入输出流、内存流、打印流、缓冲流BufferedReader、扫描流Scanner、序列化与反序列化

    文章目录 第11章.Java IO编程 11.1 文件操作类:File 11.2 字节流与字符流 字节输出流:OutputStream OutputStream类 FileOutputStream类 ...

  4. python中IO编程中关于StringIO的读写问题

    阅读前请看一下:我是一个热衷于记录的人,每次写博客会反复研读,尽量不断提升博客质量.文章设置为仅粉丝可见,是因为写博客确实花了不少精力.希望互相进步谢谢!! 文章目录 阅读前请看一下:我是一个热衷于记 ...

  5. Python学习笔记:Io编程序列化

    前言 最近在学习深度学习,已经跑出了几个模型,但Pyhton的基础不够扎实,因此,开始补习Python了,大家都推荐廖雪峰的课程,因此,开始了学习,但光学有没有用,还要和大家讨论一下,因此,写下这些帖 ...

  6. Python学习笔记:IO编程StringIO和BytesIO

    前言 最近在学习深度学习,已经跑出了几个模型,但Pyhton的基础不够扎实,因此,开始补习Python了,大家都推荐廖雪峰的课程,因此,开始了学习,但光学有没有用,还要和大家讨论一下,因此,写下这些帖 ...

  7. Python之IO编程

    前言:由于程序和运行数据是在内存中驻留的,由CPU这个超快的计算核心来执行.当涉及到数据交换的地方,通常是磁盘.网络等,就需要IO接口.由于CPU和内存的速度远远高于外设的速度,那么在IO编程中就存在 ...

  8. Java基础通信_Java网络通信基础编程(必看篇)

    方式一:同步阻塞方式(BIO): 服务器端(Server): package com.ietree.basicskill.socket.mode1; import java.io.IOExceptio ...

  9. Pyton IO编程

    文章目录 IO编程简介 文件读写 StringIO和BytestIO 操作文件和目录 序列化 IO编程简介 IO指input/output,也就是输入和输出 同步IO:同步,等第一件事情干完再干其他事 ...

  10. Java IO 编程

    Java IO 编程 提供了大量的Input和output 方法. 一个类File 和五个接口四个抽象类 File 类 唯一一个与文件本身操作的类,这个类可以进行操作文件路径的指派,可以创建或者删除文 ...

最新文章

  1. 报名 | 第二届“大数据在清华”高峰论坛
  2. 何恺明团队新作:图像分割精细度空前,边缘自带抗锯齿,算力仅需Mask R-CNN的2.6%...
  3. 三、 UIView封装的简单动画
  4. 后台UI专辑模板有这些就够了!
  5. 八大算法思想(二)------------------递归算法
  6. Samba服务器安装测试
  7. 汇编学习--7.11--内存寻址
  8. winpe修复计算机无法启动,pe系统windows启动修复工具怎么使用
  9. 《Python黑帽子:黑客与渗透测试编程之道》读书笔记(一):网络基础
  10. 【已解决】vue项目地址栏的图标不显示
  11. 会计信息系统复习资料
  12. 如何在win10下配置MySQL环境变量?
  13. linux下内存如何释放,如何释放linux的内存
  14. 崩坏星穹铁道PC、安卓、iOS三端配置要求
  15. pdf转换成jpg转换器教程
  16. 8086汇编工作环境_[C语言]什么是编辑器和编译器,什么是集成开发环境?编译原理又是什么?
  17. 当心,别被微信小程序火爆的假象所欺骗!
  18. 手把手教你如何追女生
  19. 七年交易经验,倾囊分享中长线交易秘诀
  20. 项目实训2021.07.07

热门文章

  1. 大学生IT创业计划书
  2. 松下plc安装序列号afpsgr7_《松下PLC 编程软件 FPWINGR7 操作手册 中文高清版》.pdf...
  3. 《黑客攻防技术-系统实战》开篇讲解
  4. 得力计算机dl1526第15个音乐,得力dl1526乐谱 | 手游网游页游攻略大全
  5. android 系统GPS模块
  6. vs2013编译驱动错误-Inf2Cat,signability test failed
  7. 曹则贤:从一元二次方程到规范场论 | 中国科学院2022跨年科学演讲
  8. selenium所有检测点和绕过方式[运行命令后被检测/打开就被检测/环境检测]
  9. 18个国外优质图片素材
  10. 【病毒查杀】CAD杀毒方法