問題タブ [overlapped-io]
For questions regarding programming in ECMAScript (JavaScript/JS) and its various dialects/implementations (excluding ActionScript). Note JavaScript is NOT the same as Java! Please include all relevant tags on your question; e.g., [node.js], [jquery], [json], [reactjs], [angular], [ember.js], [vue.js], [typescript], [svelte], etc.
windows - GetLastError が ERROR_OPERATION_ABORTED を返した場合、GetOverlappedResult の lpNumberOfBytesTransfered パラメータは有効ですか?
私のプロジェクトでは、シリアル ポート (RS232) から読み書きする必要があります。オーバーラップ IO を使用しており、読み取りと書き込みに 2 つの個別のスレッドを使用しています。
すぐに完了しない書き込み操作を発行すると、2 つのイベントで待機 (WaitForMultipleObjects) を開始します。オーバーラップされた構造体の hEvent メンバーに割り当てられたイベント、および停止イベント。スレッドを停止する場合は、SetEvent() を呼び出して停止イベントを通知します。これにより、待機関数が戻ります。書き込み操作がまだ保留中のため、CancelIO() を呼び出して操作をキャンセルします。次に、GetOverlappedResult() で bWait パラメーターを True に設定して、操作が完了するのを待ちます。操作が完了すると、GetOverlappedResult() は False を返し、GetLastError() は ERROR_OPERATION_ABORTED を返します。
ここに私の質問があります:
GetOverlappedResult() が False を返し、GetLastError() が ERROR_OPERATION_ABORTED (完了したがキャンセルされた操作を示す) を返す場合、lpNumberOfBytesTransfered パラメータは有効ですか? つまり、lpNumberOfBytesTransfered は、取り消される前に書き込まれた実際のバイト数を教えてくれますか? または、この場合、lpNumberOfBytesTransfered パラメータは未定義ですか?
c++ - ReadFile と重複したエラー
ReadFile に問題があり、重複しています。
まず、ReadFile を 0 と重ねて使用します
for() を使用すると、printf() を使用してバイトを確認できます
そして今、私は多数のバリアントを1つ持っています
ReafFile を 2 回使用する必要があります。この 2 回目は、offset 値と highoffset 値を指定して Overlapped() を使用しています。
しかし、 for() は最初の ReadFile をスローするのと同じバイトを出力します。 memset() でバッファーをクリーニングするか、別のバッファーを使用してみましたが、常に同じバイトが表示されます
おそらく Overlapped() はどこに行くべきかを ReadFile に指示し、1024 バイトを読み取り、それをバッファに保存しますが、何も起こりません。バッファには、overlapped() = 0 と同じ最初のバイトがあります。
これは完全なコードです
VB.NET
c++ - OVERLAPPED 構造体の参照カウント
とても興味深い記事を見つけました。頭を包み込めないことが1つだけあります。( http://molecularmusings.wordpress.com/2011/08/31/file-system-part-1-platform-specific-api-design/ ) 著者は、同期および非同期のファイル操作を処理できる File クラスについて説明しています。 . 非同期操作の場合、彼は非同期操作を内部的に追跡する自己完結型のオブジェクトを使用します。クラスは次のようになります。
そして、次のように使用されます。
今、私は疑問に思っています:ReferenceCountedItem<OVERLAPPED>* m_overlapped;
変数の役割は何ですか? これがどういうわけか参照をカウントすることは知っていますが、特にコンストラクターに構造が渡されていないため、ここでどのように使用されているかわかりませんOVERLAPPED
。orメソッドOVERLAPPED
で使用される構造体について、このクラスはどうなりますか? 記事では指定されていないため、クラスを実装しようとしました。ReadAsync
WriteAsync
ReferenceCountedItem
これがどのようにつながっているのか、私にはほとんどわかりません。誰かがそれについてもう少し説明できるかもしれません。さらに情報が必要な場合は、お知らせください。
c++ - OVERLAPPED 操作 (および IOCP ?) を使用した複数のファイルの読み取りと精緻化
基本的に特定のフォルダーを再帰的にトラバースし、特定のファイルごとにハッシュを計算する、作成した C++ Win32 プログラムを改善する方法を見つけようとしています (MD5 としましょうが、CPU の高価な計算のいずれかである可能性があります)。 . これは I/O バウンドのアプリケーションであるため、ほとんどの場合、プロセスは I/O が終了するのを待っているため、可能な限り多くの CPU を使用していません。スレッド プールを使用してこれを行っても、おそらく (私が間違っているのでしょうか?) 問題は解決されず、すべてのスレッドが I/O の完了を待ってブロックされ、さらにコンテキスト切り替えのオーバーヘッドが発生します。
そのため、重複した読み取りを使用してこれを行うことを検討し始めています。処理する新しいファイルを収集するたびに、ブロックされていない読み取り操作をキューに入れ、1 つのスレッドで完了コールバックを処理し、受信したすべてのチャンクをブロックハッシュします。キュー自体から...理論的には、これによりプロセスがI / O待機でハングするのを回避でき、CPU使用率が増加するため、全体的な速度が向上するはずです。
次の質問があります。
- これにより、アプリケーションの全体的なパフォーマンスが向上すると思いますが、そうですか? そうでない場合、なぜですか?
- I/O 完了イベントは、読み取り操作と同じ順序になるように保護されていますか? つまり、ファイルのオフセット A、B、および C から N バイトを読み取ると、A、B、および C の完了イベントをその順序で取得できますか、それとも予測できない順序で到着する可能性がありますか?
- このメカニズム全体を実装するためのライブラリまたはいくつかのコード サンプルを探しています。IOCP を使用する必要がありますか? 複数のファイル I/O の例が見つからないようです。見つかったものはすべて、1 つのファイルでの読み取りの重複、またはソケットを使用した IOCP の例にすぎません。正しい方向を教えてもらえますか?
- この場合、スレッドプールは役に立たないでしょうか? シングル スレッド アプローチで十分です (たとえば、nginx/libevent アプローチに従う)。
代替ソリューションで何かに答えないでください。私はできる限り最善の方法で OVERLAPPED 操作キューを実装したいだけです。他のものには興味がありません (もちろん、私のシナリオでより効率的であることが証明されていない限り)。
編集:
ソフトウェアの現在の実装は何ですか(もちろん、アプリはこれとまったく同じではありません。アイデアを提供するためだけです):
ありがとう。
winsock2 - 完了パケットが利用可能な場合に I/O 完了ポートがブロックされないようにするにはどうすればよいですか?
Microsoft の I/O Completion Port (IOCP)メカニズムを使用して非同期ネットワーク ソケット通信を管理するサーバー アプリケーションがあります。一般に、この IOCP アプローチは、私の環境では非常にうまく機能しています。ただし、ガイダンスを求めているエッジ ケース シナリオに遭遇しました。
テストの目的で、私のサーバー アプリケーションは、ギガビット LAN を介して単一のクライアントにデータをストリーミングしています (たとえば、約 400 KB/秒)。クライアントのイーサネット ケーブルを LAN から切断するまでは、すべて問題ありません。この方法でケーブルを切断すると、クライアントが消えたことをサーバーがすぐに検出できなくなります (つまり、クライアントの TCP ネットワーク スタックは、接続の終了の通知をサーバーに送信しません)。
その間、サーバーはクライアントへの呼び出しを続けWSASend
ます...これらの呼び出しは非同期であるため、「成功」したように見えます (つまり、データは OS によってソケットのアウトバウンド キューにバッファリングされます)。
これがすべて起こっている間、私は で 16 個のスレッドをブロックしGetQueuedCompletionStatus
、ポートから完了パケットが利用可能になったときにそれらを取得するのを待っています。クライアントのケーブルを切断する前に、完了パケットの絶え間ないストリームがありました。ここで、(予想どおり) すべてが停止したように見えます... 約 32 秒間。32 秒後、IOCP は再びアクションを開始FALSE
し、null 以外のlpOverlapped
値を返します。 GetLastError
121 を返します (セマフォのタイムアウト期間が終了しました。) エラー 121 はWSASend
、クライアントがなくなったと TCP スタックが判断した後、最終的にタイムアウトになったというアーティファクトだとしか思えません。
クライアントがなくなったことを把握するためにネットワーク スタックが 32 秒かかっても問題ありません。問題は、システムがこの決定を行っている間、私の IOCP が麻痺していることです。たとえばWSAAccept
、同じ IOCP に投稿されるイベントはGetQueuedCompletionStatus
、失敗した完了パケット (エラー 121 を示す) が受信されるまで、ブロックされている 16 のスレッドのいずれによっても処理されません。
これを回避するための私の最初の計画はWSAWaitForMultipleEvents
、 を呼び出した直後にを使用することWSASend
でした。ソケット イベントが (たとえば 3 秒) 以内に通知されなかった場合は、ソケット接続を終了して先に進みます (IOCP への広範なブロック効果を防ぐため)。残念ながら、WSAWaitForMultipleEvents
タイムアウトに遭遇することはないようです (したがって、非同期ソケットは非同期であるという理由でシグナルを送信されるのでしょうか? または、TCP キューへのデータのコピーがシグナルの対象となりますか?)
私はまだこれをすべて整理しようとしていますが、IOCP ハングを防ぐ方法について誰かが洞察を持っていることを望んでいました。
その他の詳細: 私のサーバー アプリケーションは、8 コアの Win7 で実行されています。IOCP は最大 8 つの同時スレッドを使用するように構成されています。私のスレッドプールには 16 個のスレッドがあります。十分な RAM、プロセッサ、および帯域幅。
ご提案やアドバイスをよろしくお願いします。