c - 创建/删除一系列相同大小的文件后 NTFS 磁盘空间不足

标签 c windows ntfs virtual-drive disk-io

我在处理一个大型项目时遇到了一个非常奇怪的问题。我在一个分区上写入了一堆相同大小的文件(尝试了 RAM 磁盘和通过 diskmgmt.msc 创建的虚拟磁盘)。当没有足够的可用空间来容纳另一个文件时(如 GetDiskFreeSpaceExW 所报告),我会删除先前创建的一个(仅一个) 并写入新文件。然后,我删除另一个旧文件并写入一个新文件,无限循环(因此,您可能会将分区视为大小相同的文件的环形缓冲区)。经过一系列写入删除操作(从几百到几千)后,我在写入新文件时遇到了 no free space 错误(在此之前,GetDiskFreeSpaceExW 报告足够的空间)。我让我的几位同事尝试在他们的硬件上重现该问题,但问题没有再次出现。

为了澄清一些事情,这里是确切的算法:

  1. 选择文件大小(例如 S 字节)
  2. 使用 GetDiskFreeSpaceExW 检查可用空间
  3. 如果 free_space > S:写入大小为 S 的新文件并转到 2
  4. 否则:删除一个文件并转到 2

需要注意的是,我将数据写入大小为 4096 字节的 block 中的文件(问题可能会也可能不会重新出现,具体取决于 block 大小)。文件大小为 5MB。 NTFS 分区大小为 21 MiB。簇大小为 512 B(同样,更改这些参数会影响结果)。使用这些参数,在创建第 684 个文件期间会发生失败。它不取决于我使用的是 RAM 磁盘还是虚拟磁盘(因此,这不是特定实现的问题)。

我分析了故障后生成的磁盘镜像转储,发现文件碎片严重。 Chkdsk 在实验之前和之后都没有报告任何问题。系统日志中未发现任何错误。

我的上网本(Dell Inspiron 1110)的可能相关参数:

  • Pentium SU4100,相对较慢的双核 x64 CULV CPU (1.3 GHz)
  • Windows 7 旗舰版 x64 版
  • 2 GB 内存

有人知道发生了什么以及如何调试它吗?我在哪里可以找到更多信息?我已经没有主意了,我需要尽快解决这个问题......

UPD:当我写入文件数据时会出现问题(即 write() 失败),不会当我创建文件时。所以,看起来我并不缺少 MFT 条目。

UPD2:回答一些提出的问题

  • 该分区是新格式化的分区,因此文件没有特定属性,没有目录结构,什么都没有
  • 权限为默认
  • 没有 .lnk,没有硬链接(hard link) - _仅_我编写的文件
  • 所有文件都写入根目录,不再创建目录
  • 文件名只是文件的序号(即 1、2、3...)
  • 没有备用数据流,文件是使用“fopen()”创建的,使用“fwrite()”写入并使用“fclose()”关闭
  • 确实创建了 $Txf
  • 没有坏簇,这是一个虚拟(或 RAM)磁盘

最佳答案

很好的 NTFS 问题,但这里不是所有信息。目录结构是怎样的?有这方面的 LINK 文件吗?您是否在驱动器上使用压缩?卷影副本?

您不会用完 MFT 空间,因为文件/目录的数量是恒定的。这意味着 MFT 是静态的。此外,MFT 预留空间将用于磁盘空间不足的场景。我已经用完了 NTFS 卷上的每个簇。

对于发生的事情有几种解释:

1) $Log 文件可能已增大。这是回滚日志。

2) 如果驱动器上存在不一致的权限,则文件安全信息的 @SII 文件可能会增大

3) 如果该卷上的某些文件有指向它们的 .lnk/快捷方式文件,系统会将每个目标的 GUID 放入索引中。 (如果您在资源管理器中单击两次文件,您将获得 .lnk 文件 - 在最近的文档中!)

4) 目录结构不是静态的(或者文件名长度不统一),目录的 $index 缓冲区的大小可能会增加。

5) 如果您在该驱动器上有系统卷目录,则可能有卷影副本和其他操作系统特定数据。

6) 备用数据流不显示在文件大小中。有吗?

7) TxF - 在 vi​​sta 及更高版本下,可能存在占用可变空间的事务层。

8) 坏簇?集群可能会变坏(但 chkdsk 可能会注意到这一点..)

9) 文件变得碎片化,并且与其他元数据一起的碎片列表太大,无法放入 MFT 记录中(不太可能,因为您的文件很小并且没有很长的文件)

10) 使用硬链接(hard link)还会在驱动器上放置更多数据。

我把这些都列出来供其他人引用!

最后一点 - 有时即使有 0 字节空闲,您也可以创建并写入一个小文件,因为 NTFS 驻留文件仅占用 MFT 记录(它们会恢复已删除的空闲记录)

关于c - 创建/删除一系列相同大小的文件后 NTFS 磁盘空间不足,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3565770/

相关文章:

c - 如何更新结构/记录数据库

windows - 在windbg中找不到符号路径

c# - 多线程代理检查器

c - 在 C 中从父进程向子进程发送信号

带有未声明变量的逗号运算符 - 为什么它可以编译?

c - 在 posix 上限制进程的脚本

c++ - 为什么 WaitForDeath() 可以杀死示例中的线程?

windows - 有没有办法做一个异步FindNextFile?

python - 在带有 Python 的 Windows 上使用符号链接(symbolic link)模块