浅谈标准I/O缓冲区

转自:http://blog.csdn.net/tennysonsky/article/details/43490985

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

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

1、全缓冲:

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

2、行缓冲:

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

3、不带缓冲:

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

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

全缓冲:

[cpp] view
plain
copy

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

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

[cpp] view
plain
copy

  1. #include <stdio.h>
  2. #include <string.h>
  3. int main(int argc, char *argv[])
  4. {
  5. FILE *fp = NULL;
  6. // 读写方式打开,文件不存在则创建
  7. fp = fopen("sunplusedu.txt", "w+");
  8. if(NULL == fp)
  9. {
  10. printf("open error\n");
  11. return 1;
  12. }
  13. char *str = "sunplusedu\n";
  14. int i = 0;
  15. while(i <= 512){ // 缓冲区大小不确定,i的大小只是一个调试值
  16. fwrite(str, 1, strlen(str), fp);    // 往文件写内容
  17. i++;
  18. }
  19. while(1);   // 程序阻塞在这里
  20. return 0;
  21. }

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

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

[cpp] view
plain
copy

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

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

[cpp] view
plain
copy

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

行缓冲:

[cpp] view
plain
copy

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

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

[cpp] view
plain
copy

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

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

1)缓冲区填满

[cpp] view
plain
copy

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

2)人为刷新缓冲区

[cpp] view
plain
copy

  1. #include <stdio.h>
  2. int main(int argc, char *argv[])
  3. {
  4. printf("hello sunplusedu");
  5. fflush(stdout); // 人为刷新
  6. while(1);
  7. return 0;
  8. }

3)程序正常结束

[cpp] view
plain
copy

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

不带缓冲:

[cpp] view
plain
copy

  1. #include <unistd.h>
  2. #include <string.h>
  3. int main(int argc, char *argv[])
  4. {
  5. char *str = "hello sunplusedu.com";
  6. // 有没有\n,缓冲区有没有填满,都没关系
  7. write(1, str, strlen(str)); // 往标准输出写内容
  8. while(1);
  9. return 0;
  10. }
时间: 2024-10-02 20:05:41

浅谈标准I/O缓冲区的相关文章

浅谈C++ IO标准库(1)

IO流:一.C++中标准IO库:1).为面向对象的标准库.2).以继承的形式设计.     A)以iostream为基类,派生出了fstream,strigstream类.注意:fstream.stringstream没有继承关系,open.close为fstream类自有的函数操作,str为stringstream自有的函数操作,故其各函数操作不可混用,而iostream中的函数操作其两子类由于继承关系可以调用.     B) 其禁用了复制和赋值操作,故IO对象不可以复制或赋值.这将导致像ve

浅谈一下缓冲区溢出

0x01 缓冲出溢出概念 缓冲区是用户为程序运行时在计算机中申请的一段连续内存,它保存了给定类型的数据. 缓冲区溢出就是在向缓冲区写入数据时,由于没有做边界检查,导致写入缓冲区的数据超过预先分配的边界,从而使溢出数据覆盖在合法数据上而引起系统异常的一种现象. 缓冲区溢出包括堆栈溢出和堆溢出. 0x02 进程内存的划分 要清楚缓冲区溢出的原理,就先要对计算机执行程序的内存结构加以分析. 根据不同的操作系统,一个进程可能被分配到不同的内存区域去执行,但不管什么样的操作系统.什么样的计算机架构,进程使

泛型编程与C++标准模板库 : 浅谈sort()排序函数

以前用sort排序的时候,只知道sort函数有如下两种重载方式. template< class RandomIt > void sort( RandomIt first, RandomIt last ); template< class RandomIt, class Compare > void sort( RandomIt first, RandomIt last, Compare comp ); 当时对这些参数也不是很懂,只知道一些简单的用法. 1).比如: 如下代码可以使

浅谈无缓存I/O操作和标准I/O文件操作差别

首先,先略微了解系统调用的概念: 系统调用,英文名system call,每一个操作系统都在内核里有一些内建的函数库,这些函数能够用来完毕一些系统系统调用把应用程序的请求传给内核,调用对应的的内核函数完毕所需的处理,将处理结果返回给应用程序,假设没有系统调用和内核函数,用户将不能编写大型应用程序,及别的功能,这些函数集合起来就叫做程序接口或应用编程接口(ApplicationProgramming Interface,API),我们要在这个系统上编写各种应用程序,就是通过这个API接口来调用系统

浅谈无缓存I/O操作和标准I/O文件操作区别

首先,先稍微了解系统调用的概念: 系统调用,英文名system call,每个操作系统都在内核里有一些内建的函数库,这些函数可以用来完成一些系统系统调用把应用程序的请求传给内核,调用相应的的内核函数完成所需的处理,将处理结果返回给应用程序,如果没有系统调用和内核函数,用户将不能编写大型应用程序,及别的功能,这些函数集合起来就叫做程序接口或应用编程接口(ApplicationProgramming Interface,API),我们要在这个系统上编写各种应用程序,就是通过这个API接口来调用系统内

浅谈安全性攻击人为攻击的主要形式和防御

0x01 安全性攻击主要的两种方式 当前,对信息系统(包括硬件.软件.数据.人.物理环境及其基础设施)的攻击来自多方面,这些攻击我们可以宏观地分为人为攻击(主观因素)和自然灾害攻击(客观因素),这两大类的攻击都会对信息安全构成威胁.造成自然灾害攻击的自然因素包括各种自然灾害:如水.火.雷.电.风暴.烟尘.虫害.鼠害.海啸和地震等:系统的环境和场地条件,如温度.湿度.电源.地线和其他防护设施不良造成的威胁:电磁辐射和电磁干扰的威胁:硬件设备自然老化,可靠性下降的威胁等.因为自然灾害往往不可预知和抗

蚂蚁变大象:浅谈常规网站是如何从小变大的(九)(转)

原文:http://blog.sina.com.cn/s/blog_6203dcd60100y2gd.html          [第十二阶段 :传输协议.接口.远程调用]   这一部分主要谈谈关于协议.接口和远程调用相关的内容.本来这一部分应该在之前就有比较详细的讨论,不过我放到后面来,足见其重要性.特别是在系统越来越多的时候,这几个东东直接决定了我们的开发速度和运维成本. 好,接下来我们一个个的看. 1.传输协议 到目前为止,在不同系统之间获取数据的时候,你是采用那种方式呢? 我们简单看一个

浅谈SQL Server 对于内存的管理

简介 理解SQL Server对于内存的管理是对于SQL Server问题处理和性能调优的基本,本篇文章讲述SQL Server对于内存管理的内存原理. 二级存储(secondary storage) 对于计算机来说,存储体系是分层级的.离CPU越近的地方速度愉快,但容量越小(如图1所示).比如:传统的计算机存储体系结构离CPU由近到远依次是:CPU内的寄存器,一级缓存,二级缓存,内存,硬盘.但同时离CPU越远的存储系统都会比之前的存储系统大一个数量级.比如硬盘通常要比同时代的内存大一个数量级.

浅谈栈帧(二)

接上一篇:浅谈栈帧(一) 上一篇我们简单说了一下关于堆栈与栈帧调用函数是如何调用的,堆栈中的数据是如何存储在内存中的,用了几个简单的实例去观察分析他. 这篇,我们从根本来思考一下堆栈这种东西: 其实在计算机的早期,电脑的内存是用是十分老实的,没错就是老实.他没有进行一些内存空间上的保护. 大家想想,在当内存空间不存在保护时,我们利用一个函数不断去改写计算机本身的内存,然后导致缓冲区溢出.这将使电脑崩溃,无法使用.因为内存不存在狡兔三窟,所以就老老实实的被病毒所平推了,就是是强拆,所以强拆是多么的