无缓冲IO和缓冲IO

来源:互联网 发布:手机端淘宝详情页高度 编辑:程序博客网 时间:2024/05/16 06:13
一、 不带缓冲IO和带缓冲IO操作函数

不带缓存的I/O:       read,write,open......

标准(带缓存的)I/O: fgets,fread,fwrite.....

这里使用两个对应的函数进行比较:

ssize_t write(int filedes, const void *buff, size_t nbytes)

size_t fwrite(const void *ptr, size_t size, size_t nobj, FILE *fp)


二、标准I/O对每个I/O流自动进行缓存管理(标准I/O函数通常调用malloc来分配缓存)提供了三种类型的缓存
     1) 全缓存:当填满标准I/O缓存后才执行I/O操作,磁盘上的文件通常是全缓存的。
      2) 行缓存:当输入输出遇到新行符或缓存满时,才由标准I/O库执行实际I/O操作,stdin、stdout通常是行缓存的。
      3) 无缓存:相当于read、write了,stderr通常是无缓存的,因为它必须尽快输出。

一般由系统选择缓存的长度,并自动分配,标准I/O库在关闭流的时候自动释放缓存。

也可以使用函数fflush()将流所有未写的数据送入(刷新)到内核(内核缓冲区),fsync()将所有内核缓冲区的数据写到文件(磁盘)。

在标准I/O库中也有引入缓存管理而带来的缺点就是效率问题。例如当使用每次一行函数fgets和fputs时,通常需要复制两次数据:一次是在内核和标准I/O缓存之间(当调用read和write时),第二次是在标准I/O缓存(通常系统分配和管理)和用户程序中的行缓存(fgets的参数就需要一个用户行缓存指针)之间。



三、Linux标准IO库缓存策略介绍:

    标准IO库操作是围绕着流来进行的,当我们通过fopen标准IO库函数打开一个文件,我们就使一个文件和一个IO流相关联,在这里我们把IO流和文件指针FILE*等同起来,因为所有针对IO流的操作都是通过FILE*指针来实现的。

    引入标准IO库的目的是为了提高IO的效率,避免频繁的进行read/write系统调用,而系统调用会消耗较多的资源,因此标准IO库引入了IO缓存,通过累积一定量的IO数据后,然后集中写入到实际的文件中来减少系统调用,从而提高IO效率。标准IO库会自动管理内部的缓存,不需要程序员介入。然而,也正是因为我们看不到标准IO库的缓存,有时候也会给我们带来一定的迷惑性。
   
1>标准I/O的缓存(标准输出为例)

    1)当STDOUT连接到终端设备时,那么它就是行缓存的,也就是标准IO库没看到一个新行符 \n时就刷新一次缓存(即执行一次实际的输出操作)
  
这一特性可以通过如下测试代码来验证
   int main()
  {
      printf("This Line Should be Cached...");
      sleep(3);   //这时候在终端上是看不到任何输出
      printf("\nThis Line Should be Cached Again");  //这时候可以看到第一个printf的输出,因为被换行符刷新了
      sleep(3); //这时候也只能看到一行输出,而看不到第二个printf输出的
      printf("This Line Should Not be Cached Again\n");//这时候可以看到第二个和第三个printf的输出,因为被结尾的\n刷新
      sleep(3);
      getchar();
  }

  2)当STDOUT被重定向到一个具体文件时,那么标准输出是全缓存的,也就是说只有当输出缓存被塞满或者调用fflush或fclose时才会执行实际的写入操作,这里就不给出具体例子,可以通过freopen将STDOUT重定向到一个具体文件来进行测试。

 2> 标准出错STDERR

为了尽快的看到出错信息,标准出错是不带任何缓存的
0 0
原创粉丝点击