微前端架构如何改变企业的开发模式与效率提升
1220
2022-09-16
什么是稀疏文件(Sparse File)
稀疏文件主要由 0 构成:
为何会有这种奇怪的文件呢?有些软在创建文件的时候,会先给文件提供空间,然后再逐渐把数据写入文件,这些文件包括:
数据库文件:aOracle Temporary TablespacesMS SQL Backup files虚拟机文件VMDKNTFS Metadata 文件$BadCluster$ Usnjrnl:$j
举例说明:你创建了一个 60GB 的虚拟机磁盘文件,在正常情况下,该文件要占用 60GB 的物理磁盘空间。
但在大多数情况下虚拟磁盘并未写满,例如下图,虚拟机内的操作系统本身仅占用了 9.29GB,还有 50.7GB 的剩余空间,如果在物理硬盘上创建完整 60GB 的虚拟磁盘文件未免太浪费了:
所以稀疏文件包含有大量的 0,但文件系统并没有真正使用磁盘上的物理块来存储这些 0,NTFS 文件系统是怎样做到这点的呢?我们使用三个工具来分析:fsutil、FlexHex和Aactive@Disk Editor,前者是 Windows 自带,需要以管理员身份进入命令提示符运行。
FlexHex 和 Aactive@ Disk Editor 的压缩包-。
1、创建一个 4MB 的文件,以 16 进制给出文件大小:
fsutil file createnew silly.txt 0x400000
该文件的是正常文件,数据写入了磁盘,可以用命令证实非稀疏文件:
注:数据写入磁盘了么?其实这一点存疑,文末会有讨论,这里暂且认为是这样。
用 FlexHex 也可以看到 0 被真实的分配了,因为是黑色的字体:
但是保存大量的 0 是很不划算的,因为数据写入磁盘需要花时间,还要占用成本高昂的存储空间。所以我们可用这样做:在文件的属性里设置某种标志,指明哪些部分是稀疏部分(全 0,不用写入磁盘),哪些部分是真实写入磁盘。这样做的好处是:
避免将大量的 0 写入磁盘,提升了写入速度在搜索文件时,只搜索真正写入的部分,不搜索稀疏部分,提升了搜索速度。
2、将silly.txt转换为稀疏文件:
fsutil sparse setflag silly.txt
用命令证实这一点:
也可以用 Aactive@ Disk Editor 证实这一点。右键选择 silly.txt 文件:
之后点选左边的 Attribute $10 -> $STANDARD_INFORMATION ->File Permissions,可见 Sparase File 位已经被置1:
我们再进入 Attribute $80 -> Flags,Sparse 位也被置1:
再往下进入 DATA -> Data run:
可见本文件被分配了 1024个“簇”(也叫分配单元),每个簇是 4096 字节(默认值,可在格式化时更改),那么文件大小就是 1024*4096=4194304,也就是 4MB 字节。
3、置该文件的前 3MB 为0(不写入磁盘),后 1M 是真实数据,写入磁盘:
fsutil sparse setrange silly.txt 0 0x300000
查询稀疏范围。可见稀疏部分是文件开头之后的 0x300000 字节,后面紧跟长度为 0x100000 字节的真实写入的数据:
fsutil sparse queryrange silly.txt
如何证明这点?再次运行 Aactive@ Disk Editor,重新读入文件,发现有了2个 Data Run(之前只有一个):
第一个 Data Run告诉你该文件的稀疏部分被分配了768个簇(下方的Sparse属性是Yes),768×4096=3145728,正好是3MB。
第二个 Data Run 告诉你真正写入的部分被分配了256个簇,256×4096=1048576,正好是1MB。
这与 Windows 资源管理器的磁盘占用统计是吻合的,该文件只占用了1M的物理空间:
FlexHex 也能显示出这是稀疏文件。全 0 的灰色字就是稀疏部分,真实部分为黑底白字,右下角的”SPARSE“被突出显示:
NTFS 在读写稀疏文件时是这样处理的:稀疏属性对用户/应用程序透明。当读稀疏文件,NTFS 将返回0以替代文件中的稀疏部分;当写入稀疏文件,NTFS 需要被告知该文件是稀疏的,并标记 0 区域。
有些应用程序能够识别稀疏文件,有些则不能。比如用记事本打开稀疏文件,修改几个字符再保存,该文件就变为普通文件了,复制或移动稀疏文件也是如此,因为稀疏文件需要特殊的处理方式。Windows 提供了一些这方面的API:
GetVolumeInformationA- lpFileSystemFlags 输出参数包含一个标志列表FILE_SUPPORTS_SPARSE_FILESDeviceloControl - FSCTL_SET_SPARSE- FSCTL_SET_ZERO_DATA -FSCTL QUERY ALLOCATED500 个大小为 50MB 的稀疏文件,总容量为 24.4GB,但却一个字节也没有存入物理磁盘:
for /l %%x in (1,1,500) do (echo %%xfsutil file createnew %%x.txt 0x3200000fsutil sparse setflag %%x.txtfsutil sparse setrange %%x.txt 0 0x3200000)
你可以把这些文件考入剩余空间为 100MB 的磁盘,但如果其中某几个文件逐渐增大,磁盘就会被写满。另外,如果你使用的空间被“磁盘配额”限制,那也是按照 24.4GB 计算的,哪怕没有写入任何数据。
最后,我们讨论一下稀疏文件的安全性问题。2016 年的一篇文章提到一个有趣的反分析技巧。你可以将一个小巧的可执行文件转换为一个巨大的稀疏文件,且不会影响到可执行文件的加载。但如果有人试图复制或移动该文件进行分析,那么他将得到一个臃肿的文件。
// SparseMaker.cpp - taken from "pch.h"#include
sparsemaker.exe helloworld.exe 1073741824
这样就把一个几十k的小文件转换为 1GB 大小的稀疏文件。
讨论:fsutil 创建稀疏之辩
译者在编译本文的过程中产生了一个疑问,与大家讨论。
回顾本文第 1 步的命令行,fsutil 创建了一个文件,虽然内容都是 0 ,但编辑器 FlexHEX 认为是真实写入的数据,所以用黑色字体显示(稀疏部分的数据用灰色字体)。其实这里就存疑,数据并没有真正的写入磁盘。
在实验中发现, 在不同的文件系统上,fsutil 创建文件的处理方法不同。比如创建一个 10GB 的文件,在 FAT/exFAT 分区上写入了很长时间,说明是实打实的写入数据,但在 NTFS 分区上却是在命令行按下回车键后的一瞬间就创建完成,很明显磁盘不可能有如此高的写入速度,fsutil 只能是采用了“类似于”稀疏文件的创建方法。为何说“类似于”而非就是稀疏文件呢?我们还是做实验:
在 NTFS 分区上创建 10GB 的文件,瞬间完成:
fsutil file createnew 01.txt 10737418240
验证该文件并非稀疏文件:
文件属性也看出给该文件分配了 1:1 的磁盘空间:
问题就在这里。我们说稀疏文件的特征是:
1 . 既有真实写入的数据,也有并未写入的数据,后者为全 0 。
2 . 文件属性报告的”大小“和”占用空间“可以不等。
本次实验创建的文件,数据并未写入磁盘,且为全 0 ,这是稀疏文件的特征。
但”大小“和”占用“却是相等,从磁盘划走了等量的剩余空间,这又是普通文件的特征,而且命令行也明确该文件不是稀疏文件。
那么这个兼具“稀疏文件”和“普通文件”特征的”类稀疏文件“到底是什么文件呢?
在网上查了很久,没有任何这方面的资料,只好作罢,如果你知道其中的关窍,可以在留言中指出,感谢。
版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。
发表评论
暂时没有评论,来抢沙发吧~