Hen*_*jer 6 windows windows-explorer filesystems
假设您有一个正在运行的进程在一段时间内写入文件。在资源管理器过程中,突出显示该文件将显示“当前大小”。随后的 F5 按键将更新该文件的当前大小,但令人惊讶的是,需要两次按键才能查看最正确的大小。按一次 F5 键只会获得更高的值。
多年来,这一直困扰着我(轻微地),我想知道为什么!
它可以在(至少)Windows 7 中重现,例如通过下载大文件。
有一个MSDN 博客描述了为什么 Windows 会按照您的描述运行。
首先让我们提一下您所看到的仅在 NTFS 上。
为了测试您所说的内容,我编写了一个小程序,每 5 秒将 40 kB 写入一个文件。该文件在每次写入之间保持打开状态。第二个程序用于FindFirstFileEx
获取当前文件大小。作为第三个我dir
在 cmd.exe 中使用。通过此设置,我可以准确地看到您所描述的内容。
此问题的原因是在 NTFS 中做出的设计决定。在 NTFS(如 Unix 文件系统)中,同一个文件可以位于两个目录中 - 这称为硬链接。这意味着您有两个目录,每个目录都有一个文件条目,并且您拥有文件本身及其属性。文件大小是属于文件的属性,因此它存储在那里。但是,如果有人想要具有文件大小等属性的目录中的文件列表,那么如果您不仅要读取目录本身,还要读取每个文件的信息,那么性能就会非常低。一个目录的数据可能会按顺序存储,但不同文件的数据可能会分散在整个光盘上。因此,NTFS 在目录条目/条目中存储文件大小的副本。
您可能已经猜到了,这也会影响性能。想想同一个文件的 10 个硬链接。每次写入文件时,您是否希望 NTFS 更新 10 个目录条目?不。因此,自 Vista 以来做出了第二个设计决定:目录条目中的数据仅在文件关闭时更新。
您可以轻松检查:运行写入文件并保持文件打开的程序。运行dir
,您将不会看到更新的大小。或者用记事本写一个文件(最后关闭文件),新的文件大小立即显示在dir
或 资源管理器中。
为什么这F5有助于刷新文件大小?Explorer 调用GetNamedSecurityInfo在内部打开文件并关闭它(您可以在SysInternals Process Monitor 中检查)。如果我调用GetNamedSecurityInfo
自己的程序然后调用,FindFirstFileEx
我会立即看到新的文件大小。因此,观察到的行为与理论所预期的完全一致。
但是为什么不立即在资源管理器中看到新的文件大小呢?似乎资源管理器首先调用FindFirstFileEx
,然后GetNamedSecurityInfo
. 所以资源管理器正在获取旧的大小,然后触发更新目录条目。如果您dir
在 cmd.exe 中运行,您可以看到目录条目现在具有新的文件大小。只是 Explorer 还不知道而已。资源管理器需要一秒钟F5才能获取最新大小,然后再次触发更新。
从应用程序开发人员的角度来看,我不会认为这是资源管理器错误 - 这是受支持的文件系统之一的特例,应用程序应该从文件系统中抽象出来。但是由于资源管理器是 Windows 的一部分,我倾向于认为 Microsoft 可以做得更好并更改函数调用的顺序以获得更好的用户体验。
顺便说一句,感谢这个非常有趣的问题!我喜欢学习这样的 NTFS 内部。
归档时间: |
|
查看次数: |
635 次 |
最近记录: |