在前面截断文件

时间:2009-04-01 15:52:11

标签: filesystems

我最近遇到的一个问题让我希望我可以丢掉文件的正面。如果你愿意,有点像“前面的截断”。在后端截断文件是一种常见的操作 - 我们做的事情甚至没有考虑太多。但是砍掉文件的正面?起初听起来很荒谬,但这只是因为我们受过训练才认为这是不可能的。但在某些情况下,垂直操作可能很有用。

一个简单的例子(当然不是唯一或必然是最好的例子)是FIFO队列。您正在将新项目添加到文件末尾,并从前面将项目从文件中提取出来。文件随着时间的推移而增长,前面有一个巨大的空白空间。对于当前的文件系统,有几种解决此问题的方法:

  • 删除每个项目后,复制 剩下的物品要更换它,和 截断文件。虽然它有效, 这个解决方案非常昂贵 时间,明智的。
  • 监视空白区域的大小 前面,当它到达时 特定的大小或百分比 整个文件大小,移动一切 并截断文件。这很多 比以前更有效率 解决方案,但仍然花费时间 项目在文件中移动。
  • 在中实现循环队列 文件,在洞中添加新项目 作为项目的文件的前面 除去。这可以非常有效, 特别是如果你不介意的话 事情摆脱的可能性 在队列中排序。如果你照顾 关于订单,有潜力 不得不移动物品。但在 一般来说,循环队列很漂亮 易于实施和管理磁盘 太空了。

但是如果有一个lop操作,从队列中删除一个项目就像更新文件开头标记一样简单。事实上,就像截断文件一样简单。那么,为什么没有这样的操作?

我对文件系统实现有点了解,并且没有看到任何特殊原因这很难。它看起来像所有它需要的是另一个单词(dword,也许?)每个分配条目,以说明文件在块中的开始位置。对于1美元以下100美元以下的驱动器,这种功能似乎是一个相当小的代价。

如果您可以像在最后截断一样有效地删除文件的前面,那么还有哪些其他任务会变得更容易?

您能想到这个功能无法添加到现代文件系统的任何技术原因吗?其他非技术原因?

7 个答案:

答案 0 :(得分:14)

在支持稀疏文件的文件系统上“打孔”并在任意文件位置删除数据非常容易。操作系统只需将相应的块标记为“未分配”。从文件开头删除数据只是此操作的一个特例。所需要的主要是一个将实现这样一个操作的系统调用:ftruncate2(int fd,off_t offset,size_t count)。

在Linux系统上,这实际上是通过fallocate系统调用实现的,方法是指定FALLOC_FL_PUNCH_HOLE标志以清除范围,使用FALLOC_FL_COLLAPSE_RANGE标志完全删除该范围内的数据。请注意,可以指定的范围存在限制,并且并非所有文件系统都支持这些操作。

答案 1 :(得分:6)

前面的截断文件似乎不难在系统级实现。

但是有问题。

  • 第一个是编程级别。在随机访问中打开文件时,当前范例是使用从文件开头的偏移量来指出文件中的不同位置。如果我们在文件的开头截断(或从文件的中间执行插入或删除),这不再是一个稳定的属性。 (虽然appendind或从末尾截断不是问题)。

换句话说,截断开头会改变唯一的参考点,这是不好的。

  • 在系统级别使用存在,如您所指出,但很少见。我相信大多数文件的使用都是一次写入多次写入,所以即使截断也不是一个关键特性,我们可能没有它(有些事情会变得更加困难,但没有什么是不可能的)。

我们想要更复杂的访问(确实需要)我们以随机模式打开文件并添加一些内部结构信息。此信息也可以在多个文件之间共享。这导致我们看到最后一个问题,可能是最重要的问题。

  • 从某种意义上说,当我们使用具有某种内部结构的随机访问文件时...我们仍然使用文件,但我们不再使用文件范例了。典型的这种情况是我们想要执行插入或删除记录的数据库,而不关心它们的物理位置。数据库可以将文件用作低级实现,但出于优化目的,某些数据库编辑器选择完全绕过文件系统(考虑Oracle分区)。

我认为没有任何技术原因导致我们无法完成所有工作,目前在使用数据库作为数据存储层的文件的操作系统中完成。我甚至听说NTFS在数据库的内部有许多共同点。操作系统可以(并且可能在某些特定功能中)使用另一个范例而不是文件一。

总而言之,我认为这不是技术问题所有,只是范式的改变,删除开头肯定不是当前的文件范例,而是一个大而有用的变化来强制改变任何东西。

答案 2 :(得分:1)

NTFS可以通过其稀疏文件支持执行类似的操作,但通常没那么有用。

答案 3 :(得分:0)

我认为那里有一个鸡与蛋的问题:因为文件系统没有有效地支持这种行为,人们没有编写程序来使用它,而且因为人们没有编写程序来使用它,文件系统支持它的动力很小。

您可以随时编写自己的文件系统来执行此操作,也可以修改现有文件系统(尽管“在野外”使用的文件系统可能非常复杂,您可能从头开始更容易)。如果人们发现它足够有用,它可能会流行; - )

答案 4 :(得分:0)

实际上有记录库文件系统 - IBM有一个,我相信DEC VMS也有这个功能。我似乎记得两个允许(允许?我猜它们仍然在周围)删除和插入文件中的随机位置。

答案 5 :(得分:0)

还有一个名为head的unix命令 - 所以你可以通过以下方式执行此操作:

head -n1000 file > file_truncated

答案 6 :(得分:0)

可以分两步实现这一目标

long fileLength; //file total length
long reserveLength; //reserve length until the file ending
int fd; //file open for read & write

sendfile(fd, fd, fileLength-reserveLength, reserveLength);
ftruncate(fd, reserveLength);
相关问题