我继续读到 fread()
和 fwrite()
是缓冲库调用。在 fwrite()
的情况下,我知道一旦我们写入文件,它就不会写入硬盘,它会填充内部缓冲区,一旦缓冲区已满,它就会调用 write()
系统调用将数据实际写入文件。
但我无法理解这种缓冲在 fread()
的情况下是如何工作的。在 fread()
的情况下缓冲是否意味着,一旦我们调用 fread()
,它将读取比我们最初要求的更多的数据,并且额外的数据将存储在缓冲区中(这样当第 2nd fread()
发生时,它可以直接从缓冲区给它而不是去硬盘)?
我也有以下疑问。
- 如果
fread()
像我上面提到的那样工作,那么首先调用fread()
会读取等于内部缓冲区大小的数据吗?如果是这种情况,如果我的fread()
调用请求的字节数超过内部缓冲区大小,会发生什么情况? - 如果
fread()
像我上面提到的那样工作,那意味着在fread 的情况下肯定会发生对内核的至少一次
。但是在read()
系统调用()fwrite()
的情况下,如果我们在程序执行期间只调用一次fwrite()
,我们不能肯定地说write()
系统调用被调用。我的理解正确吗? - 操作系统会维护内部缓冲区吗?
fclose()
是否刷新内部缓冲区?
最佳答案
现代系统中有许多不同级别的缓冲或缓存。这可能是典型的:
- C 标准库
- 操作系统内核
- 磁盘 Controller (特别是如果使用硬件 RAID)
- 磁盘驱动器
当您使用 fread()
时,如果您要求的更少,它可能会要求 8 KB 左右。这将存储在用户空间中,因此在下一次顺序读取时没有系统调用和上下文切换。
内核也可以预读;有一些库函数可以提示如何针对您的特定应用程序执行此操作。操作系统缓存的大小可能为千兆字节,因为它使用主内存。
磁盘 Controller 也可以预读,并且在小型系统上可以有高达数百兆字节的缓存。它在预读方面做不到那么多,因为它不知道当前文件的下一个逻辑 block 在哪里(实际上它甚至不知道它正在读取什么文件)。
最后,磁盘驱动器本身有一个缓存,大概 16 MB 左右。像 Controller 一样,它不知道它正在读取什么文件。多年来,一个磁盘 block 为 512 字节,但最近随着数 TB 磁盘的出现,它变得更大(几 KB)。
当您调用 fclose()
时,它可能会释放用户空间缓冲区,但不会释放其他缓冲区。
关于c - fread 和 fwrite 在处理内部缓冲区时有何不同?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26051181/