将文件拆分为更多文件是否必然意味着部分/全部总体内容将不在原来的位置?

将文件拆分为更多文件是否必然意味着部分/全部总体内容将不在原来的位置?

我猜想,给定一个特定大小的文件,并非其所有字节在磁盘上都是连续的(或者它们会吗?只是因为存在“对磁盘进行碎片整理”这一短语,我认为它们不会)。但至少从应用的角度来看,它们是。我的意思是,我可以使用head -c [-]n+tail -c [-]n提取文件的一部分,将其视为连续的字节序列。

假设一个文件有 10 个字节长并且包含所有相等的字节,例如

$ cat someFile
AAAAAAAAAA

是否有可能将其分成两个文件,例如someFile.part1someFile.part2,这样

$ cat someFile.part1
AAAAA
$ cat someFile.part2
AAAAA

实际上没有任何字节被移动到任何地方,也就是说这 10 个字节仍然准确地位于它们之前的位置?

毕竟,名称someFile必须以某种方式映射到内容实际开始的物理位置(在磁盘上或操作系统(或内核?)让我处理的某种虚拟内存上)。在某种程度上,我认为someFile与指针和长度没有太大区别,比如0xabc/ 10,而目标文件是0xabc/50xac1/ 5。也许我受到了我的 C++ 经验和真正不存在的文件系统经验的影响:D


我本身对这样做并不感兴趣。我很好奇了解程序如何lxsplit工作,以及他们的优势所在。主要是出于好奇,但也许,为什么不,自己尝试写一个。

答案1

一般情况下,分割文件总会导致文件内容被复制。据我所知,Linux 没有提供任何其他方式分割文件的机制。

这几乎就是整个故事,但又不完全是……

Linux 使用文件系统驱动程序来管理磁盘上的文件,写入磁盘的文件系统有时可以由其他程序操作通常而文件系统不是由 Linux 挂载的。例如调试文件对于 ext2/ext3/ext4

但是,如果程序操作文件系统本身的字节,则它可以执行的操作存在严格限制......

背景

在大多数(所有?)文件系统中,文件和目录名称与文件数据分开存储。诸如文件所有权和时间戳之类的元数据也可以存储在通常称为“Inode”的单独位置中。

这允许将两个文件名附加到同一个文件(也称为硬链接)。


文件数据存储在块中。 ext4 的默认块大小为 4KiB(4096 字节)。通常,仅保存一个字节就需要整个块,但随后可以“免费”将更多字节保存到文件中,直到块满为止。

当第一个块已满并且需要写入更多字节时,文件系统必须找到新的(可用)块。然后:

  • 它标记新块不可用,以便没有其他文件尝试使用它
  • 并记录该块在文件中的位置

不同的文件系统对这两件事有不同的技术,但要求始终是相同的。文件系统驱动程序尽力确保新块立即跟随文件中先前的块,但这不能保证。当下一个块已分配给不同的文件时,就会发生碎片。

文件什么时候可以悄悄地共享一些块?

一些文件系统和一些块级存储具有执行重复数据删除的能力。如果写入一个块的确切内容与另一个块的确切内容匹配,则可能只保留一个块。有时这意味着重复项永远不会被写入,有时这意味着它们被追溯删除。

作为马库斯·穆勒指出某些文件系统可以执行重复块删除。

它也是一个LVM的特点这发生在块级别,在文件系统的知识之外。

硬限制

假设,您可以通过创建新的索引节点、为该索引节点添加文件名,然后将块从一个索引节点重新分配到另一个索引节点来操作文件系统。

同样,Linux 没有这种机制,但是如果您知道如何操作,就没有什么可以阻止您使用硬盘驱动器上的实际字节来实现这一点。

[通常]不可能的是在不移动字节的情况下将文件分割到任意位置。块大小是不可协商的。对于大多数文件系统,文件中间不能有一半已使用的块。

这意味着在您的示例中,(几乎)肯定会写入一个新块,因为 10 个字节不是 4096 或任何其他常见块大小的倍数。

然而,不同的文件系统具有不同的功能。例如,BTRFS 支持尾部打包。

答案2

一般来说不行——这是不可能的。文件系统(除了非常专业的反例)是为面向块的存储系统(磁盘、SSD、NVME ...)设计的,文件由数据块和元数据组成。元数据包括权限、ACL 等,但尤其包括文件长度和文件块的有序列表。有一些更高级的文件组织,但所有这些都可以解析为数据块的长度和有序列表。

在所示的示例中,可以通过截断将 somefile 转换为 somefile.part1。截断涉及更改文件长度元数据,以及取消分配块列表上不再需要的任何块。这可以用任何副本来完成。创建 somefile.part2 是困难所在。在示例中,字符 5 到 10“AAAAA”不位于块的开头(块的大小是 2 字节的幂,通常为 512B 或 4096B),因此不能是文件的第一部分,除非复制到开头一个块的。

即使我们希望在块边界分割文件数据,内核文件系统代码也不会向用户空间公开此类功能,因此需要修改内核文件系统。

相关内容