在调用syncfs()之前是否需要关闭文件

时间:2017-02-09 12:13:46

标签: linux filesystems fsync

在我的嵌入式系统上,我想确保在关闭文件时安全地写入数据 - 如果系统报告数据已保存,则用户应该能够立即断电。

我知道执行此操作的正确方法是目录上的fsync()fclose()fsync()(cfr。this blog entry)。但是,在我的情况下获取目录的文件描述符有点棘手(我必须通过/proc/self/fd找回文件名并从那里派生目录)。在整个文件系统上执行syncfs()对我来说会简单得多 - 我知道这是文件系统上唯一打开的文件。

现在我的问题是:

  • 执行syncfs()是否足够?
  • 我是否需要首先fclose() FILE *(目录条目是最新的)?或fflush()是否足够?
  • 如果需要关闭,关闭前dup()文件描述符是否有用,以便我可以直接将其用于syncfs()

2 个答案:

答案 0 :(得分:1)

在文件系统(/ etc / fstab)中启用“sync”标志,默认为“async”(禁用)。启用此标志后,对相应文件系统的所有更改都将立即刷新到磁盘。这会使整个文件系统变慢,但根据您的嵌入式系统要求,这可能是一个很好的选择。

答案 1 :(得分:1)

首先,不要将标准库<stdio.h>调用(例如fprintf(3)fopen(3))与系统调用混合(例如open(2)或{{1} }或close(2))因为前者是使用进程中的库例程。缓冲区用于存储系统不知道的临时数据,其他缓冲区是操作系统接口,使系统从现在开始负责数据维护。您可以轻松区分它们,因为前者使用sync(2)描述符进行操作,而最后一次使用FILE *整数描述符进行操作。

因此,如果您使用系统调用来确保您的数据已正确同步到磁盘,首先必须int 您的流程&#39;在执行文件系统fflush(3)sync(2)调用之前缓冲数据。

不保证fsync(2) sync(2)fclose(3)时间,或close(2)之前atexit()回调过程中exit()。{br> /> 出于性能原因,操作系统缓冲区被写入延迟,而close(2)不是使其触发此类事件的事件。只是认为许多进程可以同时读取和写入同一个文件,并且每个触发文件系统刷新的close(2)都可能很难实现。操作系统会定期,umount(2)系统调用,系统关闭以及对sync(2)fsync(2)系统调用的特定调用触发此类调用。

如果您需要维护FILE *fd描述符,只需为该描述符执行fflush(fd)以确保操作系统具有fwrite(3) d或{{1}的所有缓冲区首先是数据。

最后,如果您使用fprintf(3)函数,请首先为您写入的所有<stdio.h>描述符执行fflush(),或致电FILE *告诉stdio在一次通话中同步所有描述符。然后执行fflush(NULL);sync(2)调用以确保您的所有数据都在磁盘上。无需关闭任何东西。

fsync(2)

顺便说一句,你前往FILE *fd; ... fflush(fd); fsync(fileno(fd)); /* here you know that up to the last write(2) or fwrite(3)... * data is synced to disk */ 获取描述符(你之前有过)的方法有两个原因:

  • 关闭描述符后,/dev/fd/<number>不再是您想要的描述符。通常情况下,它甚至不存在。试试这个:

    /dev/fd/<number>
  • 只能使用文件描述符来获取打开文件所属的目录。在多链接文件中,可能有数千个目录只指向它。 inode(或打开的文件结构)中没有任何内容可以让您获取用于打开该文件的路径。使用临时文件的常用方法是创建它们并立即#include <string.h> #include <stdlib.h> #include <fcntl.h> #include <unistd.h> #include <stdio.h> #include <errno.h> int main() { int fd; char fn[] = "/dev/fd/1"; close(1); /* close standard output */ fd = open(fn, O_RDONLY); /* try to reopen from /dev/fd */ if (fd < 0) { fprintf(stderr, "%s: %s(errno=%d)\n", fn, strerror(errno), errno); exit(EXIT_FAILURE); } exit(EXIT_SUCCESS); } /* main */ 它们,因此没有人可以再次打开它。尽管您保留文件打开,但您可以访问它,但是没有路径指向它。