gpt4 book ai didi

c# - 使用 FileStream 和 FILE_FLAG_NO_BUFFERING 读取文件

转载 作者:可可西里 更新时间:2023-11-01 13:19:09 25 4
gpt4 key购买 nike

一些背景知识:我一直在尝试在对大文件进行 IO 时使用 FILE_FLAG_NO_BUFFERING 标志。我们正在尝试减少缓存管理器的负载,希望通过后台 IO 减少我们的应用程序对用户机器的影响。性能不是问题。尽可能多地躲在幕后是一个大问题。我有一个用于执行无缓冲 IO 的接近工作的包装器,但我遇到了一个奇怪的问题。当我使用不是 4 的倍数的偏移量调用 Read 时出现此错误。

Handle does not support synchronous operations. The parameters to the FileStream constructor may need to be changed to indicate that the handle was opened asynchronously (that is, it was opened explicitly for overlapped 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();

最佳答案

使用 FILE_FLAG_NO_BUFFERING 时,记录的要求是读取或写入的内存地址必须是物理扇区大小的倍数。在您的代码中,您允许随机选择字节数组的地址(因此不太可能是物理扇区大小的倍数),然后添加一个偏移量。

您观察到的行为是,如果偏移量是 4 的倍数,则调用有效。字节数组很可能与 4 字节边界对齐,因此如果内存地址是 a,则调用有效4 的倍数。

因此,您的问题可以这样重写:为什么当内存地址是 4 的倍数时读取工作正常,而文档说它必须是 512 的倍数?

答案是文档没有对违反规则会发生什么做出任何具体保证。调用仍然有效可能会发生。电话可能无论如何都有效,但仅在偶数年的 9 月有效。无论如何调用都可能会发生,但前提是内存地址是 4 的倍数。(这很可能取决于读取操作中涉及的特定硬件和设备驱动程序。仅仅因为它在你的机器上工作并不'并不意味着它对其他任何人都有效。)

首先将 FILE_FLAG_NO_BUFFERINGFileStream 一起使用可能不是一个好主意,因为我怀疑 FileStream 是否真的能保证它会把你给它的地址原封不动地传递给底层的 ReadFile 调用。相反,使用 P/Invoke 直接调用底层 API 函数。您可能还需要以这种方式分配内存,因为我不知道 .NET 是否提供任何方式来分配具有特定对齐方式的内存。

关于c# - 使用 FileStream 和 FILE_FLAG_NO_BUFFERING 读取文件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12377914/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com