pread/pwrite、缓冲区和磁盘缓存

3
如果我的代码执行类似于fd = open("/dev/sdXY", ...)以及pwrite(fd, ...)/pread(fd, ...)这样的操作,那么I/O操作是否会跳过缓存或磁盘高速缓存?假设/dev/sdXY是一个未挂载、格式化的磁盘分区(ext4、ufs等)。
我之所以问这个问题,是因为我正在开发的应用程序需要授予连续文件存储,并且我读到的唯一实现方法就是像我描述的那样。但是,如果这会导致缓存、磁盘高速缓存或其他有用功能的丢失,我可能会取消对连续存储的需求。
我还困惑于是否需要重新实现低级别的内容,因为该分区已经使用文件系统进行了格式化。我读到这种情况适用于RAW磁盘/分区。我已经知道需要处理哪些块是空闲的或正在使用,文件和文件夹结构等问题,我已经在处理这些问题了。
另一个问题:我只看到关于fopen()/fread()/fwrite()和C++的文件流的缓冲区的内容。是否正确,只有这些流和f*函数族具有某种类型的缓冲区,而open/write/read/pwrite/pread等则没有?这个缓冲区和磁盘高速缓存是相同的还是不同的?
最后一个问题:HDD的高速缓存是由其自身驱动程序处理还是由文件系统(例如ext4、ufs等)处理?
1个回答

4
简单的答案是“这取决于情况”。困难之处在于如何描述它所依赖的因素。
仅仅使用open()并不能避免内核磁盘缓存池。为了做到这一点,在Linux上您需要使用特殊选项(O_DIRECT)。但是,使用open()确实避免了使用隐藏的应用程序缓存;您可以选择从哪里读取或写入数据而不进行任何中间复制。相比之下,f*函数族确实有一个“隐藏”的应用程序缓冲区;数据经常被读入与FILE *文件流相关联的I/O缓冲区中,然后被复制到您的应用程序缓冲区中。
如果您的/dev/sdXY设备已经格式化为文件系统,但是您想要确保文件的连续存储,那么您将不得不复制大部分文件系统驱动程序以确保正确地分配空间。这不太可能是您时间和精力的明智利用。是的,您需要重新实现各种低级磁盘空间管理——这将完全不是微不足道的。此外,ext4的实现与ufs等的实现非常不同,因此您真的需要花费很多心血。

谢谢。我认为只需要处理哪些块是损坏的、自由的或正在使用,以及文件和文件夹结构。我还需要重新实现什么? - Tiago.SR
这足以让你忙一段时间了,我想——它肯定会让我忙一段时间。我得研究ext4文件系统才能知道还有什么需要担心的。_ [思考30秒...]_ 但是,我认为这是一个日志文件系统,所以你需要知道日志记录的工作原理,以及如何在不破坏分配空间连续性的情况下更改手动分配的文件。现在我想起来,我非常怀疑这是可能的。 - Jonathan Leffler
硬盘本身可能有缓存——这是另一个问题,但您可以忽略它。硬盘应该让它看起来没有这样的缓存——除非它表现得比没有这样的缓存更好。无论数据是否在硬盘缓存中,只要写入完成,写入到硬盘的任何内容都应该是安全的,即使实际上还没有写入到磁盘上。 - Jonathan Leffler

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接