2010-05-10 69 views
9

在C++中,有一个std::fwrite()将缓冲区写入磁盘上的文件。fwrite是否缓冲输出?

你可以告诉我,如果有fwrite执行内的任何缓冲区?

即,如果我多次调用fwrite()(比如说10次),它是否真的会在不同的时间调用文件I/O?

我在问这个Ubuntu 10.04环境。

回答

10

是的,它被缓冲。缓冲区的大小由BUFSIZ定义。 (Thanks @ladenedge。)十个足够大的操作将导致十个系统调用。

您也可以使用std::setbufstd::setvbuf设置您自己的缓冲区。

cstdio中的函数从C继承.C++中的首选接口是fstreamfilebuf

+2

我相信默认的缓冲区大小是'BUFSIZ',就像stdio.h中定义的一样,当然呼叫者不应该需要这些信息。 'setbuf'可以用来控制某些系统的大小。 – ladenedge 2010-05-10 20:22:04

+0

大声笑,你发布的字面确切的第二次我做了一个编辑:“lasecge 1秒前” – Potatoswatter 2010-05-10 20:22:41

6

这取决于。在大多数平台上,文件IO被缓存,因此存在fflush()调用以将缓存数据写入磁盘 - 在这方面,第一个问题的答案是(通常)是“是”,第二个是“否”。也就是说,对于任何特定的平台,无论如何不能保证这种想象 - 通常,标准只是指定了这些功能的接口,而不是它们的实现。另外,如果缓存变为“满”,调用fwrite()的相当可能会导致隐式刷新,在这种情况下调用fwrite()实际上可能会触发文件IO - 尤其是在调用fwrite()具有大量数据时。

+1

库IO功能缓冲,但也是系统IO功能通常是;不仅如此,磁盘控制器也具有缓存。实际上,通常磁盘问题并不能确保您的输出缓存,但确保在您需要时将其真正写入磁盘。:) – 2010-05-10 20:43:44

+0

@Matteo,我知道你的意思 - 例如,如果在缓存写入磁盘之前程序崩溃,使用fwrite编写错误日志可能会很有意思。幸运的是,对于那个... fflush – Mac 2010-05-10 20:47:50

+0

“标准只规定了这些功能的接口,而不是它们的实现”并不准确。虽然标准没有指定实现,但它确实指定了行为。在这种情况下,标准确定FILE *被缓冲(C++在17.3.1.4/1中包含C标准,而C标准定义FILE *在7.19.5.6/2中被缓冲)。 – 2010-05-10 21:00:57

0

这取决于库的实现。你可以看看如dtrussstrace来查看实现实际调用了哪些系统调用。

你为什么在意这件事?

+0

我的程序正在做很多fwrite()。它在Ubuntu 10.04上运行。我想知道在调用fwrite()出于性能原因之前是否需要自己缓冲IO。 – michael 2010-05-10 20:34:19

+0

@michael:是的,缓冲I/O。减少调用“fwrite”的次数将至少减少代码中的分支数量。由于很多处理器在分支后重新加载指令缓存,因此分支往往会降低性能。而且,执行的代码越少,程序就越快。 – 2010-05-10 21:05:18

+0

为什么不简单地分析你的代码来找到瓶颈? – WhirlWind 2010-05-10 22:02:00

0

我不相信标准对此有任何说明,但一般来说:操作系统不会决定做多少I/O操作。它可能是1它可能是10.它甚至可能更多,如果数据量很大。大多数操作系统允许你控制I/O的行为方式,但是AFAIK没有可移植的方式来执行它。 (并且通常你不想要)

2

FILE* I/O可以被缓冲,但它不一定是(它可以是不同的每个流)。此外,有多种方法可以进行缓冲(完全缓冲,其中缓冲区未被刷新,直到其已满或者对fflush进行明确调用或缓冲区未被刷新直到看到EOL时进行行缓冲)。也可以完全关闭缓冲。

您可以使用setvbuf调用更改缓冲类型。