From : https://www.gnu.org/software/libc/manual/html_node/Stream-Buffering.html
译者:李秋豪

12.20 流缓冲

通常情况下,写入流的字符会在写入前进行累积然后以块的形式异步转送而非由应用程序马上输出。相似的,流通常从主机环境以块的形式而非字节-字节的形式读入数据。这称为缓冲。

如果你正在写一个用流来交互的程序,当你设计交互接口时你需要理解缓冲是如何工作的。否则,你可能会发现输出(例如进程提示信息)不输出理想值,或者出现奇怪的行为。

这一节讲解的是在流/文件/设备之间传输设备,并不会涉及echoing, flow control, 特殊设备。如果想了解关于终端设备的通用控制操作符的信息,参考Low-Level Terminal Interface。

你可以通过使用底层I/O函数与文件描述符来来避免使用流缓冲。参考 Low-Level I/O。

12.20.1 概念与术语

一共有三种缓冲策略:(译者注:缓冲策略是写入流/文件的充分条件,不是必要的。缓冲区存在的意义就是在使用“Stream-level I/O”时从缓冲区进行异步块写入/读出,这样可以在设备堵塞的时候或者有大量的写操作时加快效率。如果一次只写入少量数据,内核一看没有堵塞,“干脆”就把缓冲区的内容写入了,反正放着也是放着)

  • 无缓冲 unbuffered :从一个无缓冲的流中读写会马上产生效果
  • 行缓冲 line buffered:当遇到一个换行符的时候字符会以块的形式读写。
  • 满缓冲 fully buffered:字符会以任意大小的块写入读出。(真的是直译。。感觉和网上一些说满的时候才读写的说法不一样,说明可能是不堵塞的时候就读写缓冲区,最多等到缓冲区满

新开的流一般是满缓冲的,只有一个例外:当流是一个可交互设备(例如终端)的时候,流将变为行缓冲。如果想了解关于如何选择缓冲策略,参考 Controlling Buffering 。通常情况下,默认会选择出最方便的缓冲策略。

在行缓冲下,以换行符结束的信息会马上输出到交互设备里——这通常是你想要的。不以换行符结尾的信息可能不会马上显示到交互设备,所以如果你想要立即显示,你需要在写入后使用fflush, 参考 Flushing Buffers.(译者注:通常使用fprintf+stderr,因为stderr默认是无缓冲的)

12.20.2 清除缓冲区

清除缓冲区意味着立即以块的形式写入缓冲区内收集的内容。有很多情况下缓冲区会自动清除:

  • 当输出缓冲区满后尝试输出。
  • 当流关闭的时候。参考 Closing Streams。
  • 当程序通过调用exit结束的时候。参考 Normal Termination。
  • 当向行缓冲缓冲区写入换行符时。
  • 当从本文件的任意流读入时。

If you want to flush the buffered output at another time, call fflush, which is declared in the header file stdio.h.如果你想要在别的时候清除缓冲区,可以使用stdio.h中声明的fflush

  • Function: int fflush (FILE *stream)

    Preliminary: | MT-Safe | AS-Unsafe corrupt | AC-Unsafe lock corrupt | See POSIX Safety Concepts.这个函数会导致与stream关联的缓冲区被写入到文件中,如果stream是一个空指针,那么fflush会导致目前打开的所有流的缓冲区被清除。这个函数将返回EOF如果发生一个写入错误,否则返回0。

  • Function: int fflush_unlocked (FILE *stream)

    Preliminary: | MT-Safe race:stream | AS-Unsafe corrupt | AC-Unsafe corrupt | See POSIX Safety Concepts. fflush_unlocked函数和fflush相同,除了它不会隐式的阻塞(block)这个stream流。

此处省略一些...

  • Function: void **_flushlbf** (void)

    Preliminary: | MT-Safe | AS-Unsafe corrupt | AC-Unsafe lock corrupt | See POSIX Safety Concepts.该函数会清除所有的行缓冲流的缓冲区,声明在stdio_ext.h头文件中。

兼容性: 有一些脑子坏掉的操作系统总是对那些以换行符为导向的输入“念念不忘”——清除一个行缓冲会导致一个换行符被写入。幸运的是,这个特性越来越少见,并且对于GNU C Library 你不用担心。

有一些情况下不去手动清除缓冲区而是忘记这件事可能是一个更好的选择,因为读写可能不是必要的而且是相对花费大的。

  • Function: void **__fpurge** (FILE *stream)

    Preliminary: | MT-Safe race:stream | AS-Unsafe corrupt | AC-Unsafe corrupt | See POSIX Safety Concepts.__fpurge 函数会把stream流的缓冲区清空,但是不会产生读写!声明在stdio_ext.h。

12.20.3 控制缓冲策略

在打开一个流之后,你通过使用setvbuf选择该流使用何种缓冲策略。

以下列出的函数和宏在头文件stdio.h中声明。

  • Function: int setvbuf (FILE *stream, char buf, int mode, size_t size)*

    Preliminary: | MT-Safe | AS-Unsafe corrupt | AC-Unsafe lock corrupt | See POSIX Safety Concepts.这个函数是用来定义stream流该采用何种缓冲策略——可以是 _IOFBF (满缓冲), _IOLBF (行缓冲), or _IONBF (无缓冲)。如果你输入的一个空指针作为buf参数,那么setvbuf会自动使用malloc申请一块内存,当你关闭流的时候,缓冲区会被清除释放掉。否则buf对应的内存块至少应该是size大小。你不应该释放掉buf对应的空间只要流还没有关闭。你应该确保buf对应的内存是静态存储的(例如使用malloc)。使用一个自动存储期限的buf块不是一个好的选择——除非在退出当前块之前关掉了流。当buf对应的数组块是缓冲区的时候,stream流i/o函数会使用这个内存块作为一些内部用途——所以你不应该试着去直接访问这个数组的值当它被使用的时候。 setvbuf 成功时返回0,否则返回非零数当mode是不可取的或者要求不能被满足。

  • Macro: int **_IOFBF**

    这个宏的值是一个整数常量表达式,可以被setvbuf函数用来是缓冲区是满缓冲的。

  • Macro: int **_IOLBF**

    这个宏的值是一个整数常量表达式,可以被setvbuf函数用来是缓冲区是行缓冲的。

  • Macro: int **_IONBF**

    这个宏的值是一个整数常量表达式,可以被setvbuf函数用来是缓冲区是无缓冲的。

  • Macro: int BUFSIZ

    这个宏的值是一个整数常量表达式,可以被setvbuf函数用来表达size,这个值被保证最小是256。 BUFSIZ 是由操作系统选择的,以此来提高i/o的效率。所以使用 BUFSIZ 作为setvbuf的大小值是一个很好的选择。事实上,你可以用过fstat 系统调用获得一个更好的值(在文件属性的 st_blksize 区域),参考 Attribute Meanings.有时候人们使用 BUFSIZ作为申请内存空间的大小值(或者作为i/o操作的内存,例如fgets)——这没什么特别的理由,除了能提高一些i/o效率。

  • Function: void setbuf (FILE *stream, char buf)*

    Preliminary: | MT-Safe | AS-Unsafe corrupt | AC-Unsafe lock corrupt | See POSIX Safety Concepts.If buf is a null pointer, the effect of this function is equivalent to calling setvbuf with a mode argument of_IONBF. Otherwise, it is equivalent to calling setvbuf with buf, and a mode of _IOFBF and a size argument of BUFSIZ.The setbuf function is provided for compatibility with old code; use setvbuf in all new programs.如果buf是一个空指针,这个函数的效果等于setvbuf使用_IONBF.否则,等效于使用 setvbuf_IOFBF BUFSIZ这两个参数。该函数是为了兼容一些老的代码,在新的程序中请使用setvbuf.

  • Function: void setbuffer (FILE *stream, char buf, size_t size)*

    Preliminary: | MT-Safe | AS-Unsafe corrupt | AC-Unsafe lock corrupt | See POSIX Safety Concepts.

    省略...这个函数是为了兼容一些BSD的老旧代码。请使用setvbuf.

  • Function: void setlinebuf (FILE *stream)

    Preliminary: | MT-Safe | AS-Unsafe corrupt | AC-Unsafe lock corrupt | See POSIX Safety Concepts.

    省略...这个函数是为了兼容一些BSD的老旧代码。请使用setvbuf.

    剩下一些不常用的函数就不翻译了。

转载于:https://www.cnblogs.com/liqiuhao/p/7667734.html

C语言 流缓冲 Stream Buffering相关推荐

  1. Java IO流 处理流--缓冲流(Buffering)

    1. 缓冲流(Buffering) 缓冲流要"套接"在相应的节点流之上,对读写的数据提供了缓冲的功能,提高了读写的效率,同时增加了一些新的方法.Java提供了四种缓冲流,常用构造方 ...

  2. GStreamer- (缓冲)Buffering

    缓冲 缓冲的目的是在pipeline中积累足够的数据,以便播放可以顺利进行而不会中断.它通常在从(慢速)并且非实时网络源读取时这样做,但也可用于实时源. GStreamer 为以下用例提供支持: 在开 ...

  3. Java基础巩固(二)异常,多线程,线程池,IO流,Properties集合,IO工具类,字符流,对象流,Stream,Lambda表达式

    一.异常,多线程 学习目标 : 异常的概述 异常的分类 异常的处理方式 自定义异常 多线程入门 1 异常的概述 1.1 什么是异常? 异常就是程序出现了不正常情况 , 程序在执行过程中 , 数据导致程 ...

  4. linux 带缓存的fwrite,文件IO编程之(六):基于流缓冲 fopen,fwrite,fput

    标准IO开发 前面分析的文件IO编程都是基于文件描述符的.这些都是基本的IO控制,是不带缓存的. 这里要讨论的IO操作是基于流缓冲的,它是符合ANSIC的标准IO处理. 标准IO提供流缓冲的目的是尽可 ...

  5. day27-API-java流的三大分类,常用的流(文件流,对象流, 缓冲流, 转换流, PW)

    文章目录 一. java流的三大类 1. 输出流和输入流 2. 字节流和字符流 3. 节点流和处理流 二. 字节流 1. 文件流 FIS和FOS 1.1 文件输出流:FileOutputStream ...

  6. Java基础知识强化之IO流笔记41:字符流缓冲流之复制文本文件案例02(使用 [ newLine() / readLine() ] )(重要)...

    1. 使用字符流缓冲流的特殊功能 [ newLine() / readLine() ] 需求:把当前项目目录下的a.txt内容复制到当前项目目录下的b.txt中  数据源: a.txt -- 读取数据 ...

  7. Storm概念学习系列之Stream消息流 和 Stream Grouping 消息流组

    不多说,直接上干货! Stream消息流是Storm中最关键的抽象,是一个没有边界的Tuple序列. Stream Grouping 消息流组是用来定义一个流如何分配到Tuple到Bolt. Stre ...

  8. iOS基础:【屏幕成像与卡顿】屏幕撕裂 Screen Tearing、 掉帧 Jank、三缓冲 Triple Buffering

    文章目录 前言 I.屏幕成像与卡顿完整的流程 1.1 扫描的流程 1.2 屏幕撕裂 Screen Tearing 1.2.1 采用[垂直同步 Vsync + 双缓冲机制 Double Bufferin ...

  9. java8中的流(Stream)

    流式编程爱 撸码就是快,流式编程好 代码传家宝 Stream API 概念: Stream 流处理,首先要澄清的是 java8 中的 Stream 与 I/O 流 InputStream 和 Outp ...

  10. -1-4 java io java流 常用流 分类 File类 文件 字节流 字符流 缓冲流 内存操作流 合并序列流...

    File类 •文件和目录路径名的抽象表示形式 构造方法 •public File(String pathname) •public File(String parent,Stringchild) •p ...

最新文章

  1. 制作安全网站的checklist
  2. C++函数指针解引用
  3. 脑源(brainsourcing)技术可以自动识别人类的偏好
  4. Linux用户和组管理,查看软件缓存,通过命令查看硬件信息(cpu,版本,序列号,内存,主板,内核等)
  5. python 在互联网应用是如此强大
  6. 转:C# Interview Questions
  7. php 获取内容页图片,织梦DEDECMS内容页获取图片URL地址的方法
  8. POJ 1228 —— “稳定”凸包
  9. Cisco系列网络设备测试命令大全
  10. java+map对象判断空值_java判断map中是否存在指定对象
  11. ftp服务器如何配置多个文件夹,ftp服务器如何配置多个文件夹
  12. 新一代Spring Web框架WebFlux!
  13. Github | 标星20k+ Facebook 开源高效词表征学习库fastText
  14. Linux之磁盘冗余阵列
  15. 第29章:字符串编辑距离
  16. 政府大数据应用案例,政府大数据治理方法
  17. 解决vscode下载太慢的问题
  18. MAXScript语法及命令
  19. 浙大pat | 浙大pat乙级 1001~1004
  20. QCC512x QCC302x 打开 BLE 功能

热门文章

  1. Drools 规则引擎的使用
  2. $(...).nicescroll is not a function报错分析
  3. 用原生javascript制作日历
  4. 【备忘】大数据爬虫项目超清视频+源码
  5. Java中常用的设计模式【模板模式】
  6. 联想笔记本thinkbook win10系统安装
  7. SHA256算法原理详解
  8. Spring源码学习一,下载Spring源码并配置gradle环境
  9. imx8mm yocto_bsp 编译
  10. 正点原子STM32f4系列其他串口通信失败问题解决