我正在使用C#直接从磁盘读取数据,并调用kernel32 ReadFile方法。我注意到,对于较大的读取(目前只以单个块读取),缓冲区大小超出了范围。
有人知道这里读取缓冲区的最大大小吗?
如果是这样的话,当我有我想要读入的剩余内存时,限制缓冲区大小的目的是什么?我理解缓冲和保持小内存占用的概念,但是为什么一个小的大小强加在我们身上呢?也许只是一个旧的Win32 API的伪制品?
编辑:从Marshal.GetLastWin32Error()收到的错误是“值不属于预期范围”。
在收到此错误之前,上限为8192字节(8KB --因此我感到困惑)。
using System;
using System.IO;
using System.Runtime.InteropServices;
using Microsoft.Win32.SafeHandles;
namespace DiskRead
{
class Program
{
public const uint GenericRead = 0x80000000;
public const uint FileShareRead = 1;
public const uint FileShareWrite = 2;
public const uint OpenExisting = 3;
[DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
private static extern IntPtr CreateFile(string lpFileName, uint dwDesiredAccess,
uint dwShareMode, IntPtr lpSecurityAttributes, uint dwCreationDisposition,
uint dwFlagsAndAttributes, IntPtr hTemplateFile);
[DllImport("kernel32.dll", SetLastError = true)]
static extern bool ReadFile(IntPtr hFile, [Out] byte[] lpBuffer,
uint nNumberOfBytesToRead, out uint lpNumberOfBytesRead, IntPtr lpOverlapped);
static void Main(string[] args)
{
string path = @"\\.\PhysicalDrive0";
IntPtr ptr = CreateFile(path, GenericRead, FileShareRead | FileShareWrite, IntPtr.Zero, OpenExisting, 0, IntPtr.Zero);
SafeFileHandle handleValue = new SafeFileHandle(ptr, true);
FileStream fileStream = new FileStream(handleValue, FileAccess.Read);
const uint numberOfBytesToRead = 8193;
uint bytesRead;
byte[] buffer = new byte[numberOfBytesToRead];
if (!ReadFile(handleValue.DangerousGetHandle(), buffer, numberOfBytesToRead, out bytesRead, IntPtr.Zero))
{
Marshal.ThrowExceptionForHR(Marshal.GetHRForLastWin32Error());
}
}
}
}提前谢谢。
发布于 2011-10-04 13:29:57
没有这样的限制。你搞错了。
显然,您受到地址空间和缓冲区是一个连续的虚拟内存块的要求的限制。在32位系统上,每个进程只能处理2GB的虚拟内存。此外,您将无法分配2GB的连续内存块。
但这些都是普遍的限制。ReadFile API将很高兴地读入尽可能大的缓冲区中。
您声称达到了8KB的限制,但是我刚刚成功地使用WriteFile和ReadFile编写和读取了一个1GB的文件。很明显,你有一些问题,但这并不是你想的那样。如果您能够显示其余的代码,特别是调用p/ code的代码,那么我肯定它会变得很明显。
现在,您已经发布了完整的代码,我们可以看到问题是什么。您不是在读取文件,而是在执行物理磁盘的读取。我明白了,这就是你所说的“直接从磁盘读取”的意思,但我认为你可以说得更具体一点!
无论如何,我不知道这里发生了什么,但问题显然不是ReadFile本身,而是您的句柄是物理磁盘而不是文件。
CreateFile的文档声明:
卷包含一个或多个挂载的文件系统。即使在CreateFile中未指定非缓存选项时,也可以根据特定文件系统的决定以非缓存的形式打开卷句柄。您应该假设所有Microsoft文件系统都以非缓存的形式打开卷句柄。对文件的非缓存I/O的限制也适用于卷。 即使数据是非缓存的,文件系统可能需要也可能不需要缓冲区对齐。但是,如果在打开卷时指定了非缓存选项,则不管卷上的文件系统如何,缓冲区对齐都是强制的。建议在所有以非缓存的形式打开卷处理的文件系统上,并遵循非缓存的I/O限制。
我认为你应该考虑问一个关于如何从物理磁盘中读取的新问题。
发布于 2011-10-07 01:07:08
我不确定这是否对你有帮助,但它可能对其他读者有帮助:
资源
发布于 2011-10-04 11:08:32
不确定要读入的缓冲区的最大大小,但缓冲区大小的根本原因是,在函数内部,可以进行检查,这样缓冲区结束后就不会写入任何数据。如果函数没有输入缓冲区大小的概念,它可以写入缓冲区的末尾,从而导致缓冲区溢出。那将是一个严重的安全漏洞。
https://stackoverflow.com/questions/7646320
复制相似问题