【问题标题】:Remove beginning of file without rewriting the whole file删除文件的开头而不重写整个文件
【发布时间】:2014-06-16 08:57:17
【问题描述】:

我有一个嵌入式 Linux 系统,它将数据存储在一个非常大的文件中,并将新数据附加到末尾。随着文件大小增长到接近可用存储空间,我需要删除最旧的数据。

问题是,我真的不能接受像往常一样将大量数据“向上”移动到文件所需要的中断 - 长时间锁定文件只是为了重写它(加上这是闪存介质,会对闪存造成不必要的磨损)。

可能最简单的方法是将文件拆分为多个较小的文件,但这有几个与数据处理方式相关的缺点 - 所有“客户端”软件都需要单个文件。 OTOH它可以处理将第一条记录切成两半的“损坏”,因此不需要在记录偏移处修剪文件,只需在“某处”,例如前几个 iNode 被释放。最旧的数据无论如何都是过时的,所以文件开头更严重的损坏是完全可以接受的,只要“尾部”保持干净,并且可以随意删除多少数据 - “大约前几兆字节”是可以的,不需要“精确的前 4096KB”精度。

是否有一些方法、API、技巧、黑客可以像这样截断文件的开头?

【问题讨论】:

  • @fedorqui:“没有(便携式或文件系统中立) 方法可以从文件的开头(或中间)删除字节”。我要的是非便携式和非 fs 中性的。
  • @SF。尽管存在差异,但您可能会发现答案很有用。特别是 Joni 的链接到描述 EXT4_IOC_TRUNCATE_BLOCK_RANGE 的页面,这可能对您有用。
  • 如果您假设文件大小固定,您可以尝试基于文件的环形缓冲区实现 (i.e.)
  • @qarma:实际上,稀疏文件的技巧听起来不错。如果最大数据增长速度约为 3MB/月,文件需要很长时间才能增长到不合理的尺寸。

标签: c++ c linux file-io


【解决方案1】:

您可以使用 Linux 内核 v3.15 以上的 ext4/xfs 文件系统来实现目标。

int ret = fallocate(fd, FALLOC_FL_COLLAPSE_RANGE, 0, 4096);

看这里 Truncating the first 100MB of a file in linux

【讨论】:

    【解决方案2】:

    对于您的旧应用程序,最简单的解决方案是使用 FUSE 文件系统,它可以让它们访问底层文件,但偏移量是循环移位的。这将允许您在物理级别实现环形缓冲区。 FUSE 层相当简单,因为它只需要通过一个恒定的模文件大小来调整所有文件位置。

    【讨论】:

      【解决方案3】:

      如何设置一个单独的进程,当输出文件达到预定义的大小时重命名它(例如通过在文件名末尾添加 linux 时间)。

      这将允许您保留旧数据,并且主进程将在下次写入时重新创建输出文件。

      另一个 cron 作业可能会不时删除旧文件。

      【讨论】:

      • 这是“多文件”方法。问题是当文件占用 90% 的可用存储空间时,我希望它缩小到 80% 的可用存储空间,保留“中间”数据,而不是从头开始。
      • 然后,如果您还提供解析该文件的服务,则可以将其用作循环缓冲区:当它达到预定义的大小时,您从头开始写入。您可以使用同步字节(例如 FF)和同步后的时间戳来了解数据开始的位置
      猜你喜欢
      • 2013-05-25
      • 1970-01-01
      • 2015-09-24
      • 2021-06-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-09-08
      • 2020-10-31
      相关资源
      最近更新 更多