【问题标题】:synchronized write operation in CC中的同步写操作
【发布时间】:2011-10-05 15:53:22
【问题描述】:

我正在开发一个运行 linux 的智能相机。我从相机流媒体软件捕获图像并将图像写入 SD 卡(与相机相连)。为了编写单个 JPEG 图像,我使用了 fopen 和 fwrite C 函数。为了同步磁盘写入操作,我使用 fflulsh(pointer) 刷新缓冲区并将数据写入 SD 卡。但它似乎没有效果,因为写操作使用系统内存并且每次写操作后内存都会减少。我也结合fsync(filedesc)使用了低级的open和write函数,但同样没有效果。

只有在我卸下 SD 卡然后释放内存时才会刷新缓冲区。如何禁用此缓存写入而不是 SD 卡写入?或者如何强制将数据同时写入SD卡而不是使用系统内存?

【问题讨论】:

  • fsync(2) 应该做你想做的事,除非 SD 卡驱动程序有错误,或者你启用了写入缓存。

标签: c++ c


【解决方案1】:

sync(2) 可能是你最好的选择:

SYNC(2)                    Linux Programmer's Manual                   SYNC(2)

NAME
       sync - commit buffer cache to disk

SYNOPSIS
       #include <unistd.h>

       void sync(void);

DESCRIPTION
       sync() first commits inodes to buffers, and then buffers to disk.

BUGS
       According  to  the  standard specification (e.g., POSIX.1-2001), sync()
       schedules the writes, but may return before the actual writing is done.
       However,  since  version  1.3.20 Linux does actually wait.  (This still
       does not guarantee data integrity: modern disks have large caches.)

【讨论】:

    【解决方案2】:

    如果您使用open() 打开文件,您可以设置O_SYNC,或者按照上面的建议使用sync()

    使用fopen(),您可以使用fsync(),或使用fileno()ioctl() 的组合来设置描述符的选项。

    有关更多详细信息,请参阅此非常相似的帖子:How can you flush a write using a file descriptor?

    【讨论】:

      【解决方案3】:

      在处理特定文件时检查 fsync(2)。

      【讨论】:

        【解决方案4】:

        你可能真的无能为力。许多文件系统在内存中大量缓存,因此对文件的写入可能不会立即写入磁盘。在这种情况下保证写入的唯一方法是实际卸载驱动器。

        安装磁盘时,您可能需要指定sync 选项(在mountfstab 行中使用-oflag。这将确保至少您的写入是同步写入的。这是您应该始终用于可移动媒体的内容。

        【讨论】:

          【解决方案5】:

          仅仅因为它仍在占用内存并不意味着它没有被写入存储 - 一个干净的(与物理存储上的副本相同)数据副本将保留在页面缓存,直到其他东西需要该内存,以防应用程序稍后读回该数据。

          请注意,fflush() 并不能确保数据已写入存储 - 如果您使用 stdio,则必须先使用 fflush(f),然后再使用 fsync(fileno(f))

          如果您知道在可预见的将来您不需要再次读取该数据(在这种情况下似乎很可能),您可以在关闭前使用带有 POSIX_FADV_DONTNEED 标志的 posix_fadvise()文件。

          【讨论】:

          • 我尝试了使用 fflush() 的高级 fopen 和 fwrite 函数,以及使用 fsync() 的低级打开和写入函数。在这两种情况下,写入操作都与 SD 卡同步,但缓存始终包含写入数据的副本,因此每次写入操作后可用的系统内存都会减少。我还发现如果 SD 卡安装了 -o sync 选项,即使没有 fflush() 或 fsync() 也可以工作。然后,我尝试在每次写入操作后清除缓存:echo 1 > /proc/sys/vm/drop_caches。这会在每次写入操作后清除缓存。
          • 但是,令人惊讶的是,图像写入速度非常慢(即大约 1 张图像/秒)。即使我不清除缓存,让系统内存减少,使用 -o 同步选项挂载 SD 卡(或使用 fflush/fsync),图像保存速度保持不变(即 1 图像/秒)。图像以 10 FPS (5MP JPEG) 的速度捕获。我测量了保存功能的时间,它只给了我 60-70 毫秒的保存操作时间。但是不知道是什么东西需要这么长时间才能完成写操作。
          • @user846400:尚不清楚为什么您关心干净页面缓存页面使用的内存 - 如果需要,可以使用此类内存(即使您确实关心,也可以使用 @ 987654326@ 删除这些页面而不是 drop_caches 的大棒)。有可能您的存储卡根本没有比这更快的速度。
          • posix_fadvise() 和 POSIX_FADV_DONTNEED 解决了这个问题。感谢您的帮助。
          猜你喜欢
          • 2023-03-08
          • 1970-01-01
          • 2016-10-31
          • 2018-11-18
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2015-02-15
          • 2023-04-06
          相关资源
          最近更新 更多