首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >fflush和“没有磁盘空间”

fflush和“没有磁盘空间”
EN

Stack Overflow用户
提问于 2010-02-07 00:30:14
回答 4查看 2.4K关注 0票数 0

我在写一个程序,某种数据库。当我阅读fclose(3)手册时,我发现它调用fflush(3)FILE*缓冲区刷新到磁盘(实际上是到OS缓冲区,但现在没关系,我们总是可以调用fsync(2))。

因为我正在编写数据库,所以很明显,我希望防止数据丢失。如果没有磁盘空间,而fflush(3)fclose(3)中失败,我们将丢失数据,因为

中出现错误后使用FILE*将导致未定义的行为

因此,我考虑在fflush(3)之前显式使用fclose(3),警告用户磁盘空间偏低,并在一段时间后召回fflush(3)

我读过C标准,认为这是个好主意。实际上,在失败的fflush之后,第二个调用总是返回0(没有错误),但实际上什么也不做。fsync帮不了我(我以为数据可能会保存在内存中)。

在这种情况下,如何防止数据丢失?也许有一些经验法则。

这是我的测试代码:

代码语言:javascript
复制
#include <stdio.h>
int main()
{
    FILE *a = fopen("/tmp/1", "wb")
    if ( !a )
        perror("fopen");

    if ( fwrite("test", 1, 4, a) != 4 )
        perror("fwrite");  // always OK, cause data is buffered


    while( fflush(a) )  // ...second call will always return 0!
    {
        perror("fflush");  // if there is no disk space, I will get this perror, but ...
    }


    if ( fclose(a) )  // always ok, because calls only close(2)
        perror("fclose"); 

    return 0;
}
EN

回答 4

Stack Overflow用户

回答已采纳

发布于 2010-02-07 01:05:03

随后的fflush()操作成功的原因是没有(新的)数据要写入磁盘。第一个fflush()失败了;这是悲剧性的,但历史。随后的fflush()没有什么可做的,所以它做得很成功。

如果您正在写入数据库,您必须小心每一次写入--而不仅仅是在最后处理问题。取决于您的数据有多重要,您可能需要经历各种循环来处理问题-- DBMS很复杂的原因是有原因的,而失败的写操作就是其中之一。

处理这个问题的一种方法是预先分配数据的空间。正如其他人所注意到的,经典的Unix文件系统允许稀疏文件(在这些文件中,没有为其分配磁盘空间的空块),因此您实际上必须将一些数据写入您需要分配的每个页面上。然后,你只需要担心‘磁盘满’的问题,当你扩展空间-你知道什么时候你这样做,你可以认真处理这个问题。

在基于Unix的系统上,有多种系统调用可以帮助您同步磁盘上的数据,以及“打开”等选项,其中包括“O_DSYNC”和相关值。但是,如果您正在扩展一个文件,它们仍然会导致“空间不足”的失败,即使使用了花哨的同步选项。当您遇到这个失败时,您必须等待空间变得可用(因为您要求用户告诉您何时可用),然后再试一次写。

票数 3
EN

Stack Overflow用户

发布于 2010-02-07 00:56:30

fflush只会将C库内部缓冲区刷新到操作系统上,因此fflush不会保证数据不会丢失。

重复调用fflush (没有中间写)不会有帮助,因为您已经将数据刷新了一次。第二个fflush调用将返回成功,因为没有什么可以冲到操作系统。如果由于硬盘已满而导致fflush失败,您已经丢失了一些数据。

要将数据刷新到磁盘,需要使用fsync。

如果硬盘已经满了,你就倒霉了。防止数据丢失的唯一方法是现在使进程(以及内存中的数据:用户空间/内核文件缓冲区中的数据)保持活动状态,直到您在磁盘上找到要fsync的空间为止。如果停电了,你就会失去数据。

简而言之,如果您的硬盘已经满了,您就无法保证没有数据丢失。

票数 1
EN

Stack Overflow用户

发布于 2010-02-07 01:02:55

您可以预先分配一些合理的磁盘空间。编写、刷新和同步一些二进制零(或其他什么),然后返回到原来的位置。必要时冲洗并重复。如果需要的话记得截断。

有点痛,但应该管用。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/2215363

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档