标准I/O库提供缓冲的目的是尽可能地减少使用read和write调用的次数。它也对每个I/O流自动地进行缓冲管理,从而避免了应用程序需要考虑这一点所带来的麻烦。
不幸的是,标准I/O库最令人迷惑的也是它的缓冲。

标准I/O提供了三种类型的缓冲:
1、全缓冲:
在填满标准I/O缓冲区后才进行实际I/O操作。常规文件通常是全缓冲的。
2、行缓冲:
当在输入和输出中遇到换行符时,标准I/O库执行I/O操作。这允许我们一次输出一个字符,但只有在写了一行之后才进行实际I/O操作。标准输入和标准输出对应终端设备(如屏幕)时通常是行缓冲的。
3、不带缓冲:
用户程序每次调库函数做写操作都要通过系统调用写回内核(如系统调用函数)。标准错误输出通常是无缓冲的,这样用户程序产生的错误信息可以尽快输出到设备。

下面是各个缓冲区的验证。

1.全缓冲:

#include <stdio.h>
#include <string.h>
int main(int argc, char *argv[])
{FILE *fp = NULL;// 读写方式打开,文件不存在则创建fp = fopen("test.txt", "w+");if(NULL == fp){printf("open error\n");return 1;}char *str = "test\n";fwrite(str, 1, strlen(str), fp);  // 往文件写内容while(1);  // 程序阻塞在这里return 0;
}

运行程序发现,test.txt并没有内容。因为常规文件通常是全缓冲的,只有缓冲区满了后,才会把内容写到文件中。接下来,我们改一下上面那个例子。

#include <stdio.h>
#include <string.h>int main(int argc, char *argv[])
{FILE *fp = NULL;// 读写方式打开,文件不存在则创建fp = fopen("test.txt", "w+");if(NULL == fp){printf("open error\n");return 1;}char *str = "test\n";int i = 0;while(i <= 512){   // 缓冲区大小不确定,i的大小只是一个调试值fwrite(str, 1, strlen(str), fp);  // 往文件写内容i++;}while(1);   // 程序阻塞在这里return 0;
}

上面的例子是循环给文件写内容,让缓冲区有填满的可能,结果发现,文件是有内容的。实际上要想成功给文件写进内容,除了缓冲区填满,还有别的方法。

1)人为关闭文件,就算缓冲区没有填满,内容也会写进文件

#include <stdio.h>
#include <string.h>
int main(int argc, char *argv[])
{FILE *fp = NULL;// 读写方式打开,文件不存在则创建fp = fopen("test.txt", "w+");if(NULL == fp){printf("open error\n");return 1;}char *str = "test\n";fwrite(str, 1, strlen(str), fp);  // 往文件写内容fclose(fp);        // 人为关闭文件,就算缓冲区没有填满,内容也会写进文件  while(1);   // 程序阻塞在这里return 0;
}

2)程序正常结束,就算缓冲区没有填满,没有关闭文件,内容也会写进文件。

#include <stdio.h>
#include <string.h>int main(int argc, char *argv[])
{FILE *fp = NULL;// 读写方式打开,文件不存在则创建fp = fopen("test.txt", "w+");if(NULL == fp){printf("open error\n");return 1;}char *str = "test\n";fwrite(str, 1, strlen(str), fp);  // 往文件写内容return 0;// 程序正常结束,就算缓冲区没有填满,没有关闭文件,内容也会写进文件。
}

2. 行缓冲:

#include <stdio.h>
int main(int argc, char *argv[])
{printf("hello test");while(1);return 0;
}

运行这个程序,会发现 hello test并没有打印到屏幕上。因为标准输入和标准输出对应终端设备时通常是行缓冲的,当在输入和输出中遇到换行符时,标准I/O库执行I/O操作。如下:

#include <stdio.h>int main(int argc, char *argv[])
{printf("hello test\n");while(1);return 0;
}

除了遇到换行符,还有别的方法可以执行I/O操作。
1)缓冲区填满

int main(int argc, char *argv[])
{while(1){  // 循环打印,总有缓冲区填满的可能printf("hello test");}while(1);  return 0;
}

2)人为刷新缓冲区

#include <stdio.h>int main(int argc, char *argv[])
{printf("hello test");fflush(stdout); // 人为刷新while(1);    return 0;
}

3)程序正常结束

#include <stdio.h>
int main(int argc, char *argv[])
{printf("hello sunplusedu");return 0;// 程序正常结束
}

不带缓冲:

#include <unistd.h>
#include <string.h>
int main(int argc, char *argv[])
{char *str = "hello sunplusedu.com"; // 有没有\n,缓冲区有没有填满,都没关系write(1, str, strlen(str)); // 往标准输出写内容while(1);return 0;
}

Linux系统编程 -- IO缓冲区相关推荐

  1. Linux系统编程【文件IO、进程、进程间通信、信号、线程、互斥】

    linux系统编程 个人通过学习,手打了一份48000字的Linux系统编程的笔记,包含了[文件IO.进程.进程间通信.信号.多线程.互斥]等知识点,并给出了大量的代码案例对每个重要的知识点进行了代码 ...

  2. Linux系统编程之文件IO

    Linux系统编程之文件IO 文件IO第一天 一.标准IO基本概念 1.1c语言函数 (c库函数) 调用实现某一个功能,(API) 1.2系统调用:内核中的程序接口,应用程序和硬件设备之间的中间层 1 ...

  3. Linux系统编程25:基础IO之亲自实现一个动静态库

    本文接:Linux系统编程24:基础IO之在Linux下深刻理解C语言中的动静态库以及头文件和库的关系 文章目录 A:说明 B:实现静态库 C:实现动态库 A:说明 前面说过,库其实就是头文件和和.a ...

  4. linux原子过程,linux系统编程:IO读写过程的原子性操作实验

    所谓原子性操作指的是:内核保证某系统调用中的所有步骤(操作)作为独立操作而一次性加以执行,其间不会被其他进程或线程所中断. 举个通俗点的例子:你和女朋友OOXX的时候,突然来了个电话,势必会打断你们高 ...

  5. linux系统io编程,Linux系统编程(1) —— 文件IO

    本文主要对Linux系统中文件I/O的基本操作进行说明. 在Linux系统编程中,对文件进行处理的流程,通常是: 打开文件 读写文件 关闭文件 Linux内核对每一个进程维护一个打开的文件列表, 该文 ...

  6. 【Linux】一步一步学Linux系统编程教程汇总(暂时暂停更新......)

    00. 目录 文章目录 00. 目录 01. 概述和标准 02. 文件操作 03. 进程概念 04. 进程间通信 05. 多线程 06. 信号 07. 同步与互斥 08. 高级IO 09. 其它 10 ...

  7. 【Linux系统编程】Linux系统调用

    00. 目录 文章目录 00. 目录 01. 系统调用概述 02. 系统调用实现 03. 系统调用和库函数的区别 04. 附录 01. 系统调用概述 系统调用顾名思义,说的是操作系统提供给用户程序调用 ...

  8. 【Linux | 系统编程】Linux系统编程(文件、进程线程、进程间通信)

    文章目录 Linux系统编程 文件IO open/close函数 read/write函数 文件描述符 阻塞.非阻塞 fcntl函数 lseek函数 传入传出参数 文件系统 文件存储 文件操作 sta ...

  9. 【学习笔记】Linux 系统编程入门

    Linux 系统编程入门 静态库与动态库 静态库命名规则 静态库的制作 静态库使用 动态库制作 动态库使用 加载动态库 静态库的优缺点 动态库的优缺点 Makefile 文件命名 工作原理 变量 模式 ...

  10. Linux系统编程1——系统函数

    文章目录 前言 一.C标准函数与系统函数的区别 1.什么是系统调用 2.文件描述符 3.相关函数 3.1 open函数 3.2 close函数 3.3 read函数 3.4 write函数 3.5 l ...

最新文章

  1. python用def编写calsum函数_Python函数
  2. Linux Tomcat安装
  3. 【OpenCV】OpenCV实战从入门到精通之 -- 常用数据结构和函数(Point、Scalar、Size、Rect、cvtColor)
  4. dex、apk完整性校验
  5. 汽车电子测试系统搭建
  6. ActivityMq的使用(小例子)
  7. Python爬虫架构
  8. 二级路由dhcp关闭连不上wifi_如何做到让家里WiFi真正全覆盖的几个布线方案
  9. 单片机及开发板介绍(学习笔记)
  10. Opencv裁剪图片大小
  11. 二进制漏洞挖掘之angr‘s Reaching Definition Analysis(二)
  12. 使用Clang作为编译器 —— Clang 中的Diagnostic flags
  13. bboss redis组件使用实例
  14. html5猜大王游戏,5月8日维护:新副本金兜洞兕大王部分测试
  15. [附源码]Java计算机毕业设计SSM东北鹿产品售卖网站
  16. development 和 production 模式的区别
  17. Mac下转换APFS格式的移动硬盘分区为“Mac OS扩展(日志式)”或其它
  18. 解决MPS运行中出现Unsupported major.minor version错误问题
  19. 工作中的遇到的命令备忘录
  20. JS 唤起QQ对话框

热门文章

  1. MySQL — 利用命令:获取系统当前时间、打开系统服务、Mysql命令界面快速回到之前的语句
  2. JSP中用request.setAttribute()后,在action中为什么取不到值?
  3. 解读I2C协议和读写流程
  4. Linux下查杀进程的方法说明
  5. wxWindows的事件表机制
  6. BZOJ1013球形空间产生器sphere 高斯消元
  7. 一些实用的方法整理(与语言无关)
  8. css中的.clearfix是什么意思?
  9. [多线程学习笔记] 一个线程安全的队列
  10. shell编程规范与变量2