【发布时间】:2016-04-28 22:04:18
【问题描述】:
一点背景知识:在对大文件进行 IO 时,我一直在尝试使用 FILE_FLAG_NO_BUFFERING 标志。我们正在尝试减少缓存管理器的负载,希望通过后台 IO,我们将减少我们的应用程序对用户计算机的影响。性能不是问题。尽可能多地在幕后工作是一个大问题。我有一个接近工作的包装器来做无缓冲的 IO,但我遇到了一个奇怪的问题。当我使用不是 4 的倍数的偏移量调用 Read 时出现此错误。
句柄不支持同步操作。 FileStream 构造函数的参数可能需要更改以指示句柄是异步打开的(即,它是为重叠 I/O 显式打开的)。
为什么会这样?这条信息不是自相矛盾吗?如果我添加异步文件选项,我会得到一个 IOException(参数不正确。)
我想真正的问题是这些要求,http://msdn.microsoft.com/en-us/library/windows/desktop/cc644950%28v=vs.85%29.aspx,与这些 4 的倍数有什么关系。
下面是演示问题的代码:
FileOptions FileFlagNoBuffering = (FileOptions)0x20000000;
int MinSectorSize = 512;
byte[] buffer = new byte[MinSectorSize * 2];
int i = 0;
while (i < MinSectorSize)
{
try
{
using (FileStream fs = new FileStream(@"<some file>", FileMode.Open, FileAccess.Read, FileShare.None, 8, FileFlagNoBuffering | FileOptions.Asynchronous))
{
fs.Read(buffer, i, MinSectorSize);
Console.WriteLine(i);
}
}
catch { }
i++;
}
Console.ReadLine();
【问题讨论】:
-
该标志未包含在 FileOptions 枚举中可能是有原因的。此外,使用该标志时必须遵守requirements; FileStream 可能不会跟随它们,因为它没有公开该标志。
-
是的,但它存在于底层 Win32 API 中是有原因的。我知道有要求。我已经多次阅读该链接。如果您告诉它,FileStream 将跟随它们。 “读取和写入操作的文件访问缓冲区地址应该是物理扇区对齐的,这意味着在内存中的地址对齐是卷的物理扇区大小的整数倍”与 4 有什么关系?
-
值 4 在这里是相关的,因为这是 CLR 为 32 位进程中的托管对象地址保证的对齐方式。否则为 32 位操作系统的幻数。否则,这与磁盘驱动程序所接受的内容几乎没有关系。您可以通过在非托管内存 Marshal.AllocHGlobal() 中分配内存来获得扇区对齐,过度分配和调整起始地址以获得对齐。否则这个选项没有暴露在框架中的原因。
-
你真的应该更多地使用 .NET。 FileStream 之类的类是非常 薄包装器。它明确允许 FILE_FLAG_NO_BUFFERING,没有例外。
-
@HansPassant 我没有找到说明
FILE_FLAG_NO_BUFFERING支持FileOption的文档,尽管您是对的 - 它正在传递给CreateFile。