4

このプログラムを実行すると

OVERLAPPED o;

int main()
{
    ..
    CreateIoCompletionPort(....);

    for (int i = 0; i<10; i++)
    {
        WriteFile(..,&o);

        OVERLAPPED* po;
        GetQueuedCompletionStatus(..,&po);
    }
}

書き込みジョブが完了するまで、WriteFile が返されなかったようです。同時に、GetQueuedCompletionStatus() が呼び出されます。この動作は、非同期 IO 操作ではなく、同期 IO 操作に似ています。

何故ですか?

4

4 に答える 4

2

ファイル ハンドルとボリュームで書き込みキャッシュが有効になっている場合、ファイル操作はキャッシュへのメモリ コピーだけで完了し、後で遅延フラッシュされる可能性があります。実際の IO は行われないため、その場合に非同期 IO を実行する理由はありません。

内部的には、各 IO 操作はIRP (IO 要求パケット)によって表されます。これはカーネルによって作成され、リクエストを処理するためにファイルシステムに渡されます。リクエストが実際のディスク コントローラ コマンドになるまで、階層化されたドライバを介して渡されます。そのドライバーは要求を行い、IRP を保留中としてマークし、スレッドの制御を返します。ハンドルがオーバーラップ IO 用に開かれた場合、カーネルはすぐに制御をプログラムに戻します。それ以外の場合、カーネルは IRP が完了するのを待ってから戻ります。

ただし、すべての IO 操作がディスクに至るわけではありません。ファイルシステムは、書き込みをキャッシュする必要があり、後で書き込む必要があると判断する場合があります。高速 IOと呼ばれる、完全にキャッシュを使用して満たすことができる操作用の特別なパスさえあります。非同期リクエストを行った場合でも、高速 IO は常に同期的です。これは、キャッシュにデータをコピーしたり、キャッシュからデータをコピーしたりするだけだからです。

プロセス モニターは、高度な出力モードで、さまざまなモードを表示し、IRP が保留中の間、ステータス フィールドに空白を表示します。

書き込みキャッシュで未処理のままにしておくことができるデータの量には制限があります。いっぱいになると、書き込み操作はすぐには完了しません。多くの操作で、一度に大量のデータを書き込んでみてください。

于 2009-05-06T18:09:06.130 に答える
1

しばらく前に、「非同期ファイル書き込みが非同期でない場合」というタイトルのブログ投稿を書きましたが、残念ながら、答えは「ほとんどの場合」でした。ここの投稿を参照してください: http://www.lenholgate.com/blog/2008/02/when-are-asynchronous-file-writes-not-asynchronous.html

その要点は次のとおりです。

  • セキュリティ上の理由から、Windows は同期的にファイルを拡張します
  • 開始する前にファイルの末尾を大きな値に設定し、終了時にファイルを正しいサイズにトリミングすることで、この問題を回避できます。
  • を使用して、キャッシュマネージャーにバッファーではなくバッファーを使用するように指示できます。 FILE_FLAG_NO_BUFFERING
  • 少なくとも強制的に使われるほど悪くはないFILE_FLAG_WRITE_THROUGH
于 2009-05-07T06:58:23.490 に答える
0

GetQueuedCompletionStatus が呼び出されている場合、WriteFile への呼び出しは同期的です (戻りました) が、非同期の場合は、戻り後でも &o を変更できます。

于 2009-05-06T17:25:06.923 に答える
0

MSDNのこのページから:

非同期書き込み操作の場合、hFile は、FILE_ フラグを使用して CreateFile 関数で開いた任意のハンドル、FLAG_OVERLAPPEDまたは socket または accept 関数によって返されたソケット ハンドルにすることができます。

また、このページから:

ハンドルが提供されている場合は、重複した I/O の完了のために開かれている必要があります。たとえばFILE_FLAG_OVERLAPPED、CreateFile 関数を使用してハンドルを取得する場合は、フラグを指定する必要があります。

于 2009-05-06T17:28:06.743 に答える