操作系统如何为文件执行缓冲?

3
我知道当你调用fwritefprintf或其他写入文件的函数时,内容并不会立即刷新到磁盘,而是被缓存在内存中。
首先,操作系统在哪里管理这些缓冲区以及如何管理?其次,如果你将内容写入文件,并稍后读取你写入的内容,假设操作系统在你写入和读取之间没有刷新内容,它如何知道必须从缓冲区返回读取?它如何处理这种情况?
我想了解这个问题的原因是我有兴趣在用户空间实现自己的缓冲方案,而不是像操作系统一样在内核空间中实现。也就是说,写入文件将被缓存在用户空间中,实际写入只会在某个特定时间点发生。因此,我还需要处理仍然在缓冲区中的内容被读取的情况。是否可能在用户空间中完成所有这些工作?
1个回答

5
首先,操作系统在哪里管理这些缓冲区以及如何管理?
函数fwrite和fprintf使用的是stdio缓冲区,它们已经完全位于用户空间。这些缓冲区可能是静态数组,也可能是malloced内存。
其次,它如何知道必须从缓冲区返回读取的内容?
事实上,它不知道,所以更改是看不到的。直到调用底层系统调用(write)才会对文件进行实际更改(即使是这样-继续阅读)。
最后,是否可能在用户空间完成所有这些操作?
不可能。好消息是内核已经有了缓冲区,因此每次进行写入时并不会实际写入文件。它将被延迟执行。如果在此期间有人试图从文件中读取,则内核足够聪明,可以从缓冲区为其提供服务。
来自TLPI的信息:
在处理磁盘文件时,read()和write()系统调用不直接启动磁盘访问。相反,它们仅在用户空间缓冲区和内核缓冲区中复制数据。
在执行磁盘文件上的I/O时,write()成功返回并不能保证数据已传输到磁盘,因为内核对磁盘I/O进行缓冲,以减少磁盘活动并迅速write()调用。在稍后的某个时间点,内核将其缓冲区写入(刷新)到磁盘。
如果在此期间,另一个进程尝试读取文件的这些字节,则内核会自动从缓存中提供数据,而不是从(过时的内容)文件中提供数据。因此您可能需要了解同步和fsync的相关信息。
一般来说,多层缓冲通常是不好的。stdio缓冲区有用的原因在于它们最小化执行的系统调用数量。如果一个系统调用更便宜,就没有人再使用stdio缓冲区了。

cnicutar,谢谢。但是我认为,对于我的目的,我可以使用stdio缓冲概念,在用户空间缓存写操作,然后稍后调用实际的写操作。因为在我的情况下,写操作不能立即执行。我大约每50毫秒检查系统中的错误,并且只有在确定没有错误时才将数据写入文件。请注意,我所说的是一个被应用程序用于可靠性的库,所以它应该适用于所有情况。也就是说,它不应该是特定于某个应用程序的。 - undefined
@MetallicPriest 从某种意义上说,这将是重新发明 stdio。只要你不期望一致性(其他进程立即看到你的修改),那应该没问题。 - undefined
所以你的意思是,在用户级别上,当stdio实际上还没有进行系统调用时,读取仍然保存在stdio写缓冲区中的内容会被返回来读取? - undefined
@MetallicPriest 不,如果stdio没有进行系统调用,对其他人来说这些更改是看不见的。 - undefined

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