3

読み取りディスクを raw モードで開く必要があるため、そのために CreateFile API 関数を使用しています。

private static FileStream OpenDisk(string drive)
{
    // Try to open hard disk drive in raw mode for reading
    SafeFileHandle safeHandle = Native.CreateFile(
        string.Format(@"\\.\{0}", drive),
        FileAccess.Read,
        FileShare.Read,
        IntPtr.Zero,
        FileMode.Open,
        FileAttributes.ReadOnly | FileAttributes.Device,
        IntPtr.Zero);

    // Check if the drive was successfully opened
    if (safeHandle.IsInvalid)
    {
        Marshal.ThrowExceptionForHR(Marshal.GetHRForLastWin32Error());
    }

    // Create file stream on the file for reading
    return new FileStream(safeHandle, FileAccess.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).

この問題を再現するサンプル コードは次のとおりです。

using (FileStream stream = OpenDisk("X:"))
{
    byte[] buffer = new byte[1000];
    while (stream.Read(buffer, 0, 1000) > 0) { }
}

私はそれが私に何を望んでいるのか本当にわかりませんか?より大きなバッファー (4096 など) を使用すると機能します。私がそれが機能すると言うとき、それは本当に(常に)機能することを意味します。バッファサイズを変更するまで、しばらくの間機能していました。内部である種の非同期バッファリングを行っていると思いますが、デフォルトのバッファリングサイズよりも大きなバッファを指定すると、それは使用されませんが、これを取り除くにはどうすればよいですか?

ありがとう

アップデート

BufferedStream を使用して読み取ろうとすると、同じ問題が発生します

using (BufferedStream stream = new BufferedStream(OpenDisk("X:"), 4096))
{
    byte[] buffer = new byte[1000];
    while (stream.Read(buffer, 0, 1000) > 0) { }
}

BufferedStream の間違った目的を理解していますか? 指定されたサイズのチャンクを読み取ってキャッシュするべきではありませんか?

4

1 に答える 1

4

つまり、ボリュームからの読み取りはバッファリングされておらず、セクター全体である必要があります。4096 のバッファー サイズでこれが実現されます。非同期 I/O と非バッファリングは一緒に行われる傾向があるため、エラー メッセージは誤解を招きます。いくつかの詳細:

CreateFile ドキュメントから:

ボリューム ハンドルは、CreateFile で noncached オプションが指定されていない場合でも、特定のファイル システムの裁量で noncached として開くことができます。すべての Microsoft ファイル システムは、ボリューム ハンドルを非キャッシュとして開いていると想定する必要があります。ファイルの非キャッシュ I/O に関する制限は、ボリュームにも適用されます。

ファイルバッファリングドキュメントから:

  • OVERLAPPED 構造体のオプションのファイル オフセットを含むファイル アクセス サイズは、指定されている場合、ボリューム セクター サイズの整数倍のバイト数でなければなりません。たとえば、セクター サイズが 512 バイトの場合、アプリケーションは 512、1,024、1,536、または 2,048 バイトの読み取りと書き込みを要求できますが、335、981、または 7,171 バイトは要求できません。
  • 読み取りおよび書き込み操作用のファイル アクセス バッファー アドレスは、物理セクターにアラインされている必要があります。つまり、ボリュームの物理セクター サイズの整数倍であるメモリ内のアドレスにアラインされています。ディスクによっては、この要件が適用されない場合があります。
于 2012-09-26T18:47:26.033 に答える