为什么一些正在写入的文件报告 0 字节但正在缩小驱动器的可用空间?

n61*_*007 1 windows metadata filesystems

根据文件系统,我偶尔会遇到在写入过程中写入“0 字节”长文件的程序,但写入会缩小驱动器报告的可用空间。示例程序正在wget下载一些大文件或ffmpeg转换视频。

写入需要足够长的时间,例如。由于某些编码、下载或其他较慢的操作,几分钟即可写入数百兆字节。这次我可以看到可用磁盘空间缩小了,根据文件系统,但是 0 字节文件仍然是 0 字节。

通常,如果我中止操作,文件会突然报告“丢失”字节并突然增长到“正确”大小。

此外,如果我使用 Total Commander's Lister 查看文件内部,我可以看到文件中确实有内容。

我想知道,这些字节在哪里?0 字节文件旁边没有“.bak”之类的文件。我的 tmp 目录在另一个驱动器上。根据任务管理器的Memory (private working set). 而且,Lister 可以显示内容!

我检查文件系统大小的方法是通过 Total Commander 的显示信息。我会定期刷新目录列表,这也会更新可用空间计数器。我也用 进行了测试dir,给出了相同的结果。我在 NTFS 上。

为什么报告的大小没有更新?其中存储的数据在哪里?

Jde*_*eBP 5

这确实是设计使然。这是 Microsoft/IBM 操作系统的长期行为,在 32 位 OS/2、16 位 OS/2、PC-DOS、MS-DOS 以及 DR-DOS(又名 Novell DOS,又名OpenDOS)。

行为是文件的目录条目仅在文件的系统文件表条目关闭时才更新,在目录列表中显示正确的上次修改时间戳、大小和分配信息。当引用它的所有进程中的所有打开句柄都关闭时,SFT 条目将关闭。正在下载“数百 MiB”的程序尚未关闭其打开的文件句柄。所以他们的 SFT 条目没有关闭。所以目录条目不会更新。

如果使用 为文件创建了一个或多个附加句柄,则该文件DosDupHandle的内部缓冲区不会写入磁盘,并且不会更新其目录条目,直到DosClose为所有句柄调用为止。
— “关闭文件”。 OS/2 Warp:控制程序编程指南和参考。IBM 公司。

在单任务 MS/PC/DR-DOS 上,这有点难以观察,尽管可以在 DesqView、Windows 3.x 386 增强模式等下观察到TASKMAX。在多任务 OS/2 上,可以定期轻松地观察它。

这种行为的一个不太受欢迎的特性是(在 FAT 卷上)在文件句柄关闭之前脏关机会导致CHKDSK看到大小为零的文件并截断​​到目前为止下载的所有内容。

这是与 UNIX 完全不同的行为,在 UNIX 中可以看到文件随着它的增长而增长,ls -l因为该ls命令查看 i-node(内存中和最新)以获取文件元数据,而不是目录条目(在本机 UNIX 文件系统上没有大小和日期信息)。DOS、OS/2 和 Windows NT 也在增加该文件。数据块被分配给文件,SFT 条目跟踪文件大小,f 节点(在 HPFS 卷上)等结构保持最新,并且正如您观察到的卷的可用空间正在减少。一个人根本看不到,dir或者任何其他报告目录条目内容的文件,文件正在增长。

Windows NT 和 NTFS 的情况与 OS/2 和 DOS 的情况非常相似。(命名法发生了变化,这对新手来说有点混乱。在 DOS 和 OS/2 的系统文件表条目中,单个进程中的文件句柄引用了 Windows NT 的文件对象,这些对象由单个进程中的句柄引用。)具有讽刺意味的是,更类似于自 Windows NT 6.0 以来较旧的 IBM/Microsoft 操作系统的行为,其中行为已更改。“新”NTFS 行为是文件的目录条目,存储在每个具有文件链接的目录中,并在列出 Win32 目录时使用(带有FindFirstFile/FindNextFile),仅在文件的文件对象关闭时更新,而附加到文件本身的元数据,从目录列表中不可见(并且只能通过诸如 的调用访问GetFileInformationByHandle),会按文件更新。

为了降低脏关机风险并看到文件大小随着文件写入而增加,我们采用了一个简单的技巧。你也仍然可以使用它。

每当关闭文件的系统文件表条目时,文件的目录条目就会更新,并且当引用它的任何进程中最后一个打开的文件句柄关闭时,SFT 条目也将关闭。 这不必是写入文件的进程打开或使用的句柄。 可以使用任何打开文件(创建一个单独的 SFT 条目)并再​​次关闭它的东西。它可以像type在另一个控制台/会话中运行的命令一样简单:

输入文件 > 空

具有讽刺意味的是,Total Commander 的 Lister 会做到这一点,每次您使用它查看正在写入的文件内容时。如果您发现了这一点,您就会一直在这里问为什么 Total Commander 的 Lister 神奇地“修复”了您的目录列表。答案可能是 Total Commander 没有什么特别之处。 任何单独打开和关闭文件都会产生相同的效果。

为了完整起见,请注意下载程序可以使用系统调用来更新目录条目。DosBufReset例如,OS/2 有。但是,这些系统调用也会刷新磁盘缓存,这不一定是人们想要的。再次打开文件然后关闭该文件句柄不会刷新磁盘缓存。