带缓冲区的iostream的机制是什么?

时间:2018-02-11 04:39:54

标签: c++

首先,在 cplusplus.com 中,它显示every stream object has a associated std::streambuf
在c ++ primer 5th中,它说:

  
      
  1. 每个输出流管理缓冲区,用于保存程序读取和写入的数据。例如,执行以下代码时   os << "please enter a value: ";
      文字字符串可能会立即打印,或操作系统可能会将数据存储在缓冲区中以便稍后打印

  2.   
  3. 有几个条件导致缓冲区被刷新 - 也就是说,要写入实际的输出设备或文件:程序正常完成,使用操纵器,如ENDL等

  4.   

根据我的理解,句子“操作系统可能会将数据存储在缓冲区(不在 缓冲区中)上面的上下文意味着流对象和操作系统都使用自己的缓冲区,即一个在进程地址空间,另一个在操作系统管理的内核空间中。

这是我的问题,

  1. 为什么每个进程/对象(如cout)都管理自己的缓冲区?为什么不直接进行系统调用并将数据直接提供给OS缓冲区?

  2. 此外,术语“刷新”是否作用于对象缓冲区或OS缓冲区?我想刷新操作实际上会唤醒系统调用并告诉操作系统立即将OS缓冲区中的数据放到屏幕上。

1 个答案:

答案 0 :(得分:1)

  
      
  1. 为什么每个进程/对象(如cout)都管理自己的缓冲区?为什么不直接进行系统调用并将数据直接提供给OS缓冲区?
  2.   

作为一个预答案,您可以始终重写流缓冲区以始终刷新到系统OS调用以进行输出(或输入)。实际上,您的系统可能已经这样做了 - 它只取决于实现。这个系统只允许在iostreams库的级别进行缓冲,但并不一定需要它。我们记得。

对于缓冲,逐字节发送或读取数据并不总是最有效的。在许多系统中如coutcin的情况下,操作系统可以更好地处理这种情况,但您可以调整iostream来处理读取套接字的输入和输出流(来自Internet连接的I / O) 。在套接字中,您可以通过Internet将单个包中的每个字符写入目标,但这可能会变得非常慢,具体取决于链接类型和链接的繁忙程度。当您读取套接字时,消息可以在数据包之间拆分,因此您需要缓冲输入,直到达到“临界质量”。有可能在操作系统级别执行此缓冲,但我发现至少我可以获得更好的性能,如果我自己处理大部分缓冲(因为通常消息的大小在整个运行时间有很大的标准偏差)。因此,iostream中的缓冲是管理输入和输出以优化性能的有用方法,当您尝试同时处理来自多个连接的I / O时,这尤其有用。

但你不能总是假设操作系统会做正确的事情。我记得有一次我们使用这个FUSE模块,它允许我们在多个计算机节点上拥有一个分布式文件系统。在编写和阅读单个字符时,它有一个非常奇怪的问题。虽然读取或写入一长串单个字符在使用ext4系统的普通硬盘上最多需要几秒钟,但同样的操作在FUSE系统上需要几天时间(忽略了我们为什么这样做的原因)。通过调试,我们发现挂起处于I / O级别,读取和写入单个字符会加剧此运行时问题。我们不得不重新编写代码来缓冲我们的读写操作。我们可以弄清楚的最好的是ext4上的操作系统自己做了缓冲,但这个FUSE文件系统在读写硬盘时没有做类似的缓冲。

在任何情况下,操作系统都可以进行自己的缓冲,但在许多情况下,此缓冲不存在或最小。在iostream端缓冲可以帮助您提高性能。

  
      
  1. 此外,术语'刷新'是作用于对象缓冲区还是OS缓冲区?我想刷新的动作实际上会引起系统调用并告诉操作系统立即将数据放入OS缓冲区中。
  2.   

我相信大多数文本都会谈到C ++中标准I / O流的“刷新”。您的程序可能无法直接控制操作系统如何处理其I / O.但总的来说,我认为操作系统和程序的I / O将与大多数系统同步。