我了解到,默认情况下,程序中的I/O被缓冲,即它们从临时存储中提供给请求程序。 我知道缓冲提高了IO性能(可能通过减少系统调用)。我见过禁用缓冲的例子,例如C中的setvbuf
。这两种模式之间的区别是什么以及什么时候应该使用另一种模式?缓冲IO与非缓冲IO
56
A
回答
90
只要希望确保输出在继续之前被写入,就需要无缓冲的输出。一个例子是C运行时库下的标准错误 - 默认情况下这通常是无缓冲的。由于错误(希望)很少,你想立即知道它们。另一方面,标准输出是缓冲仅仅是因为它假设将有更多的数据通过它。
另一个例子是日志库。如果日志消息保存在进程中的缓冲区中,并且进程转储核心,那么很可能永远不会写入输出。
此外,它不仅仅是最小化的系统调用,还包括磁盘I/O。假设一个程序一次读取一个字节的文件。使用无缓冲输入时,即使可能必须读取整个数据块(磁盘硬件本身可能有缓冲区,但仍要到磁盘控制器),每个字节都会出现(相对非常慢)的磁盘这将比内存访问慢)。
通过缓冲,整个块被一次读入缓冲区,然后单个字节从(内存中,难以置信的快速)缓冲区传递给你。
请记住,缓冲可以采取多种形式,如下面的例子:
+-------------------+-------------------+
| Process A | Process B |
+-------------------+-------------------+
| C runtime library | C runtime library | C RTL buffers
+-------------------+-------------------+
| OS caches | Operating system buffers
+---------------------------------------+
| Disk controller hardware cache | Disk hardware buffers
+---------------------------------------+
| Disk |
+---------------------------------------+
21
您想无缓冲输出,当你已经准备好向磁盘写入字节的大序列,并希望避免额外复制到中间的第二个缓冲区。
缓冲输出流将累积写入结果到中间缓冲区,只有当足够的数据已经累积(或请求flush())时才将其发送到OS文件系统。这减少了文件系统调用的次数。由于在大多数平台上文件系统调用可能很昂贵(与短memcpy相比),缓冲输出在执行大量小写操作时是一个净赢。如果已经有大量缓冲区要发送,则无缓冲输出通常会更好 - 复制到中间缓冲区不会进一步减少OS调用的数量,并且会引入额外的工作。
无缓冲输出有没有与确保您的数据到达磁盘;该功能由flush()提供,可用于缓冲和未缓冲的流。无缓冲的IO写入不保证数据已经到达物理磁盘 - 操作系统文件系统可以无限期地保存数据副本,永远不会将其写入磁盘,如果需要的话。只需要在调用flush()时将其提交到磁盘。 (请注意,close()将代表您调用flush())。
相关问题
- 1. C++缓冲流IO
- 2. IO缓冲关闭
- 3. Java IO缓冲区导航
- 4. perl中的无缓冲IO
- 5. Haskell默认io缓冲
- 6. Python文件io缓冲
- 7. 什么是IO流缓冲?
- 8. fork()和缓冲IO流
- 9. Ruby中的缓冲IO
- 10. 文件IO和缓冲区
- 11. 内存缓冲区和IO操作
- 12. 改变bash的IO缓冲设置
- 13. Erlang io:格式缓冲和效率
- 14. 使用stdio.h异步缓冲io?
- 15. 什么是文件IO流缓冲区?
- 16. Ruby中的缓冲/ RingBuffer IO + Amazon S3非阻塞区块读取
- 17. Linux缓冲区缓存对IO写入的影响?
- 18. UNIX缓冲和非缓冲I/O
- 19. SqlDataReader:缓冲与非缓冲读取器 - 如何?
- 20. 输入及IO错误:面向字节读取字符缓冲的IO
- 21. 缓冲与子
- 22. 与缓冲区
- 23. 缓冲/无缓冲通道
- 24. 缓冲区IO上的空指针异常
- 25. OSX:用于设置IO缓冲区长度的CoreAudio API?
- 26. Rails渲染/流IO类对象没有缓冲
- 27. 通过Akka IO和套接字协议缓冲区消息
- 28. IO :: Compress :: Zip从文件句柄读入缓冲区
- 29. 如何刷新Erlang中的io缓冲区?
- 30. 为什么默认缓冲区大小在Java IO中为8k?
将调用'flush()'保证它被写入磁盘?我认为只将它传递给磁盘的缓冲区。 – jrdioko 2011-07-14 23:24:58
您需要'O_SYNC'来确保写入。 – moshbear 2011-12-07 00:54:43