缓冲区概念及缓冲区溢出

 缓冲区又称为 缓存 ,是内存空间的一部分。也就是说,在内存空间中预留了一定的存储空间,这些存储空间用来缓冲出入或输出的数据,这部分预留的空间就叫做缓冲区。
  缓冲区根据其对应的 输入设备 还和 输出设备 ,分为输入缓冲区和输出缓冲区。

缓冲区的作用

  缓冲区的作用是为了解决速度不匹配的问题,高速的cpu与内存,内存与硬盘,cpu与io等速度不匹配的问题,而引人缓冲区,比如我们从磁盘里读取信息,我们先把读出的数据放在缓冲区,计算机再直接从缓冲区中读取数据,等缓冲区的数据读取完后再去磁盘中读取,这样就可以减少磁盘的读写次数,再加上计算机对缓冲区的操作大大快于对磁盘的操作,故应用缓冲区可大大提高计算机的运行速度。
  缓冲区就是一块内存区,它用在输入输出设备和 CPU 之间,用来缓存数据。它使得低俗的输入输出设备和高速的CPU能够协调工作,避免低速的输入输出设备占用CPU。解放出CPU,使其能够高效率工作。

缓冲区的类型

  缓冲区分为三种类型:全缓冲、行缓冲和不带缓冲。
  1、全缓冲
  在这种情况下,当填满标准 I/O 缓存后才进行实际I/O操作。全换冲的典型代表是对磁盘文件的读写。
  2、行缓冲
  在这种情况下,当在输入和输出中遇到换行符时,执行真正的I/O操作。这时,我们输入的字符先存放在缓冲区,等按下回车键换行时才进行实际的I/O操作。典型代表是键盘输入数据。
  3、不带缓冲

  不带缓冲也就是不进行缓冲,标准出错情况stderr是典型代表,这使得出错信息可以直接尽快地显示出来。

文件流的缓冲区大小.
设的过小,可能导致不能读出预期长度的数据
设的过大,浪费内存
所以使用的时候一般都会事先预估数据块的大小来设置buffersize
或者采取多次读取的方法来回避这个问题 

缓冲区溢出

  为了便于理解,我们不妨打个比方。缓冲区溢出好比是将十磅的糖放进一个只能装五磅的容器里。一旦该容器放满了,余下的部分就溢出在柜台和地板上,弄得一团糟。由于计算机程序的编写者写了一些编码,但是这些编码没有对目的区域或缓冲区——五磅的容器——做适当的检查,看它们是否够大,能否完全装入新的内容——十磅的糖,结果可能造成缓冲区溢出的产生。如果打算被放进新地方的数据不适合,溢得到处都是,该数据也会制造很多麻烦。但是,如果缓冲区仅仅溢出,这只是一个问题。到此时为止,它还没有破坏性。当糖溢出时,柜台被盖住。可以把糖擦掉或用吸尘器吸走,还柜台本来面貌。与之相对的是,当缓冲区溢出时,过剩的信息覆盖的是计算机内存中以前的内容。除非这些被覆盖的内容被保存或能够恢复,否则就会永远丢失。 
  在丢失的信息里有能够被程序调用的子程序的列表信息,直到缓冲区溢出发生。另外,给那些子程序的信息——参数——也丢失了。这意味着程序不能得到足够的信息从子程序返回,以完成它的任务。就像一个人步行穿过沙漠。如果他依赖于他的足迹走回头路,当沙暴来袭抹去了这些痕迹时,他将迷失在沙漠中。这个问题比程序仅仅迷失方向严重多了。入侵者用精心编写的入侵代码(一种恶意程序)使缓冲区溢出,然后告诉程序依据预设的方法处理缓冲区,并且执行。此时的程序已经完全被入侵者操纵了。 
  入侵者经常改编现有的应用程序运行不同的程序。例如,一个入侵者能启动一个新的程序,发送秘密文件(支票本记录,口令文件,或财产清单)给入侵者的电子邮件。这就好像不仅仅是沙暴吹了脚印,而且后来者也会踩出新的脚印,将我们的迷路者领向不同的地方,他自己一无所知的地方。 
  你屋子里的门和窗户越少,入侵者进入的方式就越少…… 
  由于缓冲区溢出是一个编程问题,所以只能通过修复被破坏的程序的代码而解决问题。如果你没有源代码,从上面“堆栈溢出攻击”的原理可以看出,要防止此类攻击,我们可以:  
  1、开放程序时仔细检查溢出情况,不允许数据溢出缓冲区。由于编程和编程语言的原因,这非常困难,而且不适合大量已经在使用的程序; 
  2、使用检查堆栈溢出的编译器或者在程序中加入某些记号,以便程序运行时确认禁止黑客有意造成的溢出。问题是无法针对已有程序,对新程序来讲,需要修改编译器; 
  3、经常检查你的操作系统和应用程序提供商的站点,一旦发现他们提供的补丁程序,就马上下载并且应用在系统上,这是最好的方法。但是系统管理员总要比攻击者慢一步,如果这个有问题的软件是可选的,甚至是临时的,把它从你的系统中删除。举另外一个例子,你屋子里的门和窗户越少,入侵者进入的方式就越少。

文件缓冲区的大小设置

函数原型:void setbuf(FILE *fp, char *buf);

                void setvbuf(FILE *fp, char *buf, int type, unsigned size);

头文件:#include<stdio.h>

是否是标准函数:是

函数功能: 这两个函数使得打开文件后,用户可以建立自己的文件缓冲区,而不必使用fopen函数打开文件时设定的默认缓冲区。

setbuf函数的定义中,参数buf指定的缓冲区大小由stdio.h中定义的宏BUFSIZE的值决定,缺省值default为512字节。而当buf为NULL时,setbuf函数将使文件I/O不带缓冲区。而对setvbuf函数,则由malloc函数来分配缓冲区。参数size指明了缓冲区的长度(必须大于0),而参数type则表明了缓冲的类型,其取值如下表:

setvbuf函数中参数type的取值含义

type 值

  含义

 _IOFBF

文件全部缓冲,即缓冲区装满后,才能对文件读写

_IOLBF

文件行缓冲,即缓冲区接收到一个换行符时,才能对文件读写 

 _IONBF 

文件不缓冲,此时忽略buf,size的值,直接读写文件,不再经过文件缓冲区缓冲 

返回值:无。

例程如下 应用setbuf函数指定文件的缓冲区。

#include <stdio.h>

void main( void )

{

   char buf[BUFSIZ];

   FILE *fp1, *fp2;

   if( ((fp1 = fopen( "test1.txt", "a" )) != NULL) &&

       ((fp2 = fopen( "test2.txt", "w" )) != NULL) )

   {

      /* 应用setbuf函数给文件流fp1指定缓冲区buf */

      setbuf( fp1, buf );

      /*显示缓冲区地址*/

      printf( "fp1 set to user-defined buffer at: %Fp\n", buf );

      /* 文件流fp2不指定缓冲区*/

      setbuf( fp2, NULL );

      /*信息提示不分配缓冲区*/

      printf( "fp2 buffering disabled\n" );

      fclose(fp1);

      fclose(fp2);

   }

}

例程说明:

(1)首先开辟一个大小为BUFSIZ的缓冲区,用作指定文件的缓冲区。这里,BUFSIZE为stdio.h中定义的宏,缺省值为512字节。

(2)以追加的方式和写的方式打开名为"test1.txt"和"test2.txt"的文件。

(3)应用setbuf函数给文件流fp1指定缓冲区buf,其中buf为缓冲区的首地址。并在屏幕上显示该首地址。

(4)文件流fp2不指定缓冲区,也就是第二个参数设置为NULL。并信息提示不分配缓冲区。

(5)关闭两个文件。

注意:使用setbuf函数指定文件的缓冲区时,一定要在文件读写之前。一旦用户自己指定了文件的缓冲区,文件的读写就要在用户指定的缓冲区中进行,而不在系统默认指定的缓冲区中进行。函数setvbuf的用法与setbuf类似,只是它的缓冲区大小可以动态分配,由函数的参数指定,而且缓冲区的类型也可以由参数指定。

 
  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

九天神鹰

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值