2

stdio.h FILE我知道使用直接read()/的优点之一write()是缓冲、中断处理等。因此,据我了解,所有fwrite()s 都会被缓冲,直到我执行fclose(). 到现在为止还挺好。现在,当我执行时fclose(),我会阻塞直到数据刷新到磁盘,还是fclose()在将数据交给操作系统并让它在空闲时刷新到磁盘后立即返回?

4

2 回答 2

3

有许多级别的缓冲,这取决于操作系统和许多其他事情。

通常,在您的应用程序中存在的 FILE* 中有一个内部缓冲区,该缓冲区要么被刷新到文件(或 FILE* 连接到的任何设备)

  • 当内部 FILE* 缓冲区已满时
  • 当你写了一个换行符时(如果是一行缓冲的 FILE*)
  • 当你关闭文件*
  • 当你调用 fflush()
  • FILE* 也可以是无缓冲的

对于普通磁盘文件,大多数操作系统在内核中都有缓冲,因此刷新 FILE* 缓冲区或多或少只是将内存从应用程序的缓冲区复制到操作系统内核,内核会处理在闲暇时将其异步写入实际文件,这将导致 fclose() “立即”返回。

在将数据复制到操作系统/内核缓冲区之前,操作系统可能首先必须进行一些内务处理,例如,它可能必须将数据刷新到物理文件以为更多数据腾出空间,在文件中分配空间以确保有空间等等,使它不会立即返回。

简而言之,它取决于你,你无法控制它。通常,您可以做的“最好”是使用平台相关的 API,至少允许您将操作系统缓冲区刷新到物理文件,例如 posix fsync()/fdatasync() API。

于 2012-02-21T09:44:06.253 回答
0

您的理解(至少部分)是错误的。

I/O 是缓冲的,但缓冲区大小有限制。当缓冲区溢出时,它们将被刷新。此外,许多流是行缓冲的;当你写一个换行符时,缓冲区被刷新。如果不是这种情况,输出到终端将是非常不切实际的,因为所有输出都在程序终止时出现。

我认为调用不一定会阻塞,例如,有些函数会尝试确保底层媒体与写入同步。这通常会产生“太低级”的问题,并且需要处理软件以及硬件(例如硬盘驱动器)中的缓存和缓冲区的复杂性。

于 2012-02-21T09:32:12.907 回答