我最近工作的一个问题让我希望我可以丢掉文件的正面.如果你愿意,有点像"前面的截断".在后端截断文件是一种常见的操作 - 我们做的事情甚至没有考虑太多.但是砍掉文件的正面?起初听起来很荒谬,但这只是因为我们受过训练才认为这是不可能的.但是在某些情况下,垂直操作可能很有用.
一个简单的例子(当然不是唯一或必然是最好的例子)是FIFO队列.您正在将新项目添加到文件末尾,并从前面将项目从文件中提取出来.文件随着时间的推移而增长,前面有一个巨大的空白空间.对于当前的文件系统,有几种解决此问题的方法:
删除每个项目后,将其余项目复制以替换它,并截断该文件.虽然它有效,但这种解决方案在时间上非常昂贵.
监视前面空白区域的大小,当它达到整个文件大小的特定大小或百分比时,向上移动所有内容并截断文件.这比以前的解决方案更有效,但仍然需要花费时间在文件中移动项目.
在文件中实现循环队列,在删除项目时将新项添加到文件前面的孔中.这可能非常有效,特别是如果您不介意队列中出现故障的可能性.如果你关心订单,就有可能不得不移动物品.但一般来说,循环队列很容易实现并很好地管理磁盘空间.
但是如果有一个lop操作,从队列中删除一个项目就像更新文件开头标记一样简单.事实上,就像截断文件一样简单.那么,为什么没有这样的操作呢?
我对文件系统实现有一点了解,并且没有看到任何特殊原因这很难.它看起来像所有它需要的是另一个单词(dword,也许?)每个分配条目,以说明文件在块中的开始位置.对于1美元以下100美元以下的驱动器,这样的功能似乎是一个相当小的代价.
如果您可以像在最后截断那样有效地删除文件的前面,那么还可以使其他任务变得更容易?
你能想到这个功能无法添加到现代文件系统的任何技术原因吗?其他非技术原因?
在支持稀疏文件"打孔"并在任意文件位置删除数据的文件系统上非常容易.操作系统只需将相应的块标记为"未分配".从文件开头删除数据只是此操作的一个特例.所需要的主要是一个将实现这种操作的系统调用:ftruncate2(int fd,off_t offset,size_t count).
在Linux系统上,实际上通过指定将范围置零的标志和用于完全删除该范围内数据的标志,实现了fallocate系统调用.请注意,可以指定的范围存在限制,并且并非所有文件系统都支持这些操作.FALLOC_FL_PUNCH_HOLE
FALLOC_FL_COLLAPSE_RANGE
前面的截断文件似乎不难在系统级实现.
但是有问题.
第一个是编程级别.在随机访问中打开文件时,当前范例是使用从文件开头的偏移量来指出文件中的不同位置.如果我们在文件的开头截断(或从文件的中间执行插入或删除),这不再是一个稳定的属性.(虽然appendind或从末尾截断不是问题).
换句话说,截断开头会改变唯一的参考点,这是不好的.
在系统级别使用存在,如您所指出的,但非常罕见.我相信大多数文件的使用都是一次读取多次写入,所以即使截断也不是一个关键特性,我们可能没有它(有些事情会变得更加困难,但没有什么是不可能的).
我们想要更复杂的访问(并且确实需要)我们以随机模式打开文件并添加一些内部结构信息.此信息也可以在多个文件之间共享.这导致我们看到最后一个问题,可能是最重要的问题.
从某种意义上说,当我们使用具有某种内部结构的随机访问文件时...我们仍然使用文件,但我们不再使用文件范例了.典型的这种情况是我们想要执行插入或删除记录的数据库,而不关心它们的物理位置.数据库可以将文件用作低级实现,但出于优化目的,某些数据库编辑器选择完全绕过文件系统(考虑Oracle分区).
我认为没有任何技术原因导致我们无法完成所有工作,目前在使用数据库作为数据存储层的文件的操作系统中完成.我甚至听说NTFS在数据库的内部有许多共同点.操作系统可以(并且可能在某些特定功能中)使用另一个范例而不是文件一.
综上所述,我相信这是没有技术problemat,仅仅是一个范式的变化和去除之初绝对不是在当前文件的模式,但不是一个大的和有用的足够变化,迫使所有改变任何东西.