Linux内核缓冲技术

概述


 内核空间与外围设备交换数据,用户空间与内核空间交换数据实际上是非常消耗时间的,应该尽量减少它们之间相互访问的次数,就应用了缓冲技术。其本质就是一次性读取大量数据(顺序读写)进缓冲,当需要数据的时候进入缓冲区读取数据,这样能够大大减少消耗的时候被消耗的时间,所以内核缓冲技术对于文件IO是非常重要的。

 linux中的fopen函数是open函数的封装,fopen使用了FILE结构体保存缓冲数据,在进行read和write的时候减少了用户态和内核态的切换。open没有缓冲,每次读操作都直接从文件系统中获取数据,在进行read和write的时候每次都需要进行内核态和用户态的切换。当顺序访问文件,fopen系列的函数要比直接调用open系列快;如果随机访问文件open要比fopen快。
 在上图中可以看到open每次打开文件都会产生一个结构体file来保存文件的读写信息,即使对于同时打开同一个文件,其结构体信息是不一样的。

标准IO缓冲区

 1.不缓冲:一旦有数据,立即同步到外部设备。
 2.全缓冲:(普通文件的默认类型);
  a.一旦数据填满了缓冲区,立即同步到外部设备;
  b.程序正常退出时,立即同步到外部设备;
  c.遇到 fflush() 强制同步时,立即同步到外部设备;
  d.关闭文件时,立即同步到外部设备;
  e.读取文件时 , 立即同步到外部设备;
 3.行缓冲:(最多只能缓冲一行)
  a.一旦填满,立即同步到外部设备;
  b.程序正常退出时,立即同步到外部设备;
  c.遇到 fflush() 强制同步时,立即同步到外部设备;
  d.关闭文件时,立即同步到外部设备;
  e.读取文件时 , 立即同步到外部设备;
  f.一旦遇到 '\n' 时, 立即同步到外部设备;

相关API

setbuf ( 设置文件流的缓冲区 )
    头文件:
        #include <stdio.h>
    定义函数:
        void setbuf(FILE * stream, char * buf);
    参数分析:
         stream --> 为指定的文件流
         buf --> 自定的缓冲区起始地址 
     无返回
        
setvbuf ( 设置文件流的缓冲区)
    头文件:
        #include <stdio.h>
    定义函数:
        int setvbuf(FILE * stream, char * buf, int mode, size_t size);
    参数分析:
        stream --> 指定的文件流 
        buf --> 指向自定的缓冲区起始地址
        size --> 为缓冲区大小
        mode --> 有下列几种
            _IONBF 无缓冲 IO
            _IOLBF 以换行为依据的无缓冲 IO
            _IOFBF 完全无缓冲 IO. 如果参数 buf 为 NULL 指针, 则为无缓冲 IO.
    返回值:
        成功返回 0 
        失败返回 非零 , 错误号码会被设置

使用代码

#include <stdio.h>
#include <unistd.h>
#include <string.h>
int main()
{
 
   char buff[1024];
 
   memset( buff, '\0', sizeof( buff ));
 
   fprintf(stdout, "启用全缓冲\n");
   setvbuf(stdout, buff, _IOFBF, 1024);
 
   fprintf(stdout, "这里是 runoob.com\n");
   fprintf(stdout, "该输出将保存到 buff\n");
   fflush( stdout );
 
   fprintf(stdout, "这将在程序退出时出现\n");
   fprintf(stdout, "最后休眠五秒钟\n");
 
   sleep(5);
 
   return(0);
}

https://www.runoob.com/cprogramming/c-function-setvbuf.html

总结

 1.通常磁盘上的文件是全缓冲区的;
 2.标准输入和标准输入在指向终端设备时是行缓冲,而指向文件时,则是全缓冲的;
 3.为了尽可能显示错误信息,标准错误是不带缓冲的。

posted @ 2020-12-18 21:32  ding-ding-light  阅读(232)  评论(0编辑  收藏  举报