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

标准I/O提供了三种类型的缓冲:

1、全缓冲:

在填满标准I/O缓冲区后才进行实际I/O操作。常规文件(如普通文本文件)通常是全缓冲的。

2、行缓冲:

当在输入和输出中遇到换行符时,标准I/O库执行I/O操作。这允许我们一次输出一个字符,但只有在写了一行之后才进行实际I/O操作。标准输入和标准输出对应终端设备(如屏幕)时通常是行缓冲的。

3、不带缓冲:

用户程序每次调库函数做写操作都要通过系统调用写回内核(如系统调用函数)。标准错误输出通常是无缓冲的,这样用户程序产生的错误信息可以尽快输出到设备。

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

全缓冲:

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

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

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

行缓冲:

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

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

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

除了遇到换行符,还有别的方法可以执行I/O操作。

1)缓冲区填满

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

2)人为刷新缓冲区

#include <stdio.h>int main(int argc, char *argv[])
{printf("hello sunplusedu");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系统编程】 浅谈标准I/O缓冲区相关推荐

  1. 【Linux系统编程】IO标准缓冲区

    00. 目录 文章目录 00. 目录 01. 缓冲区概述 02. 全缓冲 03. 行缓冲 04. 不带缓冲区 05. 附录 01. 缓冲区概述 标准I/O提供了三种类型的缓冲: 1.全缓冲: 在填满标 ...

  2. Linux 网络编程——浅谈 C/S 和 B/S 架构

    概述 在这个信息急剧膨胀的社会,我们不得不说人类正进入一个崭新的时代,那就是信息时代.信息时代的一个主要而显著的特征就是计算机网络的应用.计算机网络从最初的集中式计算,经过了Client/Server ...

  3. Linux网络编程——浅谈 TCP 三次握手和四次挥手

    一.tcp协议格式 二.三次握手 在 TCP/IP 协议中,TCP 协议提供可靠的连接服务,采用三次握手建立一个连接. 第一次握手:建立连接时,客户端发送 syn 包(tcp协议中syn位置1,序号为 ...

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

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

  5. 【Linux系统编程】 Linux系统调用概述

    系统调用概述 系统调用,顾名思义,说的是操作系统提供给用户程序调用的一组"特殊"接口.用户程序可以通过这组"特殊"接口来获得操作系统内核提供的服务,比如用户可以 ...

  6. Linux系统编程——Linux系统调用

    系统调用概述 系统调用,顾名思义,说的是操作系统提供给用户程序调用的一组"特殊"接口.用户程序可以通过这组"特殊"接口来获得操作系统内核提供的服务,比如用户可以 ...

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

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

  8. 【Linux系统编程】进程的控制:结束进程、等待进程结束

    结束进程 首先,我们回顾一下 C 语言中 continue, break, return 的作用: continue: 结束本次循环 break: 跳出整个循环,或跳出 switch() 语句 ret ...

  9. 编程浅谈-以一个初出茅庐的Java程序员视角

    编者是一个从事Java开发的普通软件攻城狮,迄今为止,粗粗算来不过刚刚进入编程的世界不过两年,但在这两年的光阴里,每当我抬头仰望星空(苦命加班)时脑海里总有这样一个疑问--"什么是编程&qu ...

最新文章

  1. anki 新的卡片类型_梁宝川:这一类型Anki卡片,你做了吗?
  2. HDU3338 Kakuro Extension(最大流+思维构图)
  3. 零基础带你快速入门consul-难道consul还能这样用?
  4. Service基本组成 (一)
  5. luogu1341 无序字母对
  6. 世界杯后linux进化有感?
  7. ROS笔记(32) MoveIt!关节控制器
  8. bootstrap 按钮样式单选效果_【20201117】Bootstrap前端框架学习笔记
  9. Linux下Gcc生成和使用静态库和动态库详解(转)
  10. leetcode 13 13. 罗马数字转整数 (python)
  11. file is not a zip file_如何使用JavaScript解压压缩后的zip文件
  12. PS如何使用裁切工具
  13. 剑桥: 一个完美的读书地方
  14. img标签图片自适应的样式
  15. 电脑是怎样执行编程语言的
  16. VMware拟收购云应用管理服务商Wavefront
  17. Video-based Emotion Recognition Using Multi-dichotomy RNN-DNN
  18. APP测试之安全性测试
  19. 倪文迪陪你学蓝桥杯2021寒假每日一题:1.20日(2018省赛A组第8题)
  20. opIndex多级索引笔记

热门文章

  1. andorid 第一天 搭建环境(于本博另一篇文章 ubuntu下安装andoird SDK相同内容)
  2. SqlHelper 数据库操作类
  3. 对集合变量定义赋值_SpringBoot配置加载原理(自定义加载配置)
  4. php无法查询mysql字母,php – 无法在Multi MYSQL查询语句中获取结果
  5. C#委托的定义 以及使用方式详解,更简单的理解委托。
  6. virtualenv杂记
  7. Css网格布局-Grid布局
  8. hdu 2586(LCA的离线做法)
  9. javase学习第10天(形式参数和返回值类型、包、内部类、匿名内部类)
  10. PRISM概率模型检测器初使用--骰子模型(改进版)