3


0

名前付きパイプWinAPIを使用した非同期I / O

わかりました、私は私がしたいことを達成しようとすることのさまざまな側面についていくつかの質問をしました。 今回は、名前付きパイプから読み取るだけで大​​きな問題が発生します。 これを適切に設定できれば、作業中のプロジェクトを完了するのに十分な情報を収集できたと思います。 以下に関連するすべてのコードを含めますが、私の使命はこれです。書き込みを行っていないプログラムから出力を(継続的に)読み取り、WinAPIに投稿します。 したがって、私の問題は、匿名パイプから名前付きパイプに切り替えたばかりであり、情報を取得できるように適切にセットアップしようとすると問題が発生することです。 MSDNのサンプルを基にしたフレームワークのセットアップがあります。

#define WAIT_TIME 2 // 2s
#define INSTANCES 4 // Number of threads
#define CONNECT_STATE 0
#define READ_STATE 1
#define WRITE_STATE 2
#define WORLDRD 0
#define WORLDWR 1
#define WORLDINRD 2
#define WORLDINWR 3
#define BUFSIZE 0x1000 // Buffer size 4096 (in bytes)
#define PIPE_TIMEOUT 0x1388 // Timeout 5000 (in ms)

void Arc_Redirect::createProcesses()
{
TCHAR programName[]=TEXT("EXEC_PROGRAM.exe");
PROCESS_INFORMATION pi;
STARTUPINFO si;
BOOL bSuccess = FALSE;

ZeroMemory(hEvents,(sizeof(hEvents)*INSTANCES));
ZeroMemory(outStd,(sizeof(PIPE_HANDLES)*INSTANCES));

// Prep pipes
for(int i=0;ihEvent))
                break;
        default:
            throw "ConnectNamedPipe(); failed!";
        break;
    }

    return pendingIO;
}

outStd [INSTANCES]は、以下のPIPE_HANDLES(カスタム構造体)として定義されています

typedef struct
{
    HANDLE hPipeInst;
    OVERLAPPED o1;
    TCHAR chReq[BUFSIZE];
    TCHAR chReply[BUFSIZE];
    DWORD dwRead;
    DWORD dwWritten;
    DWORD dwState;
    DWORD cbRet;
    BOOL pendingIO;
} PIPE_HANDLES, *LPSTDPIPE;

今、ここから少し迷子になっています。 どこに行くかわからない。 MSDNの例でループを使用しようとしましたが、私がしようとしていることに対して適切に動作しませんでした。 パイプの読み取り側を取得し、情報を取得する必要があります(再度、継続的に)書き込み側も開いて、書き込みが必要になる場合があります。 誰かアイデアがありますか? 匿名パイプの場合と同様に、ReadFile()を実行しようとしましたが、同じ方法で動作していないようです。

また、注意してください:私はそれを使っているので、コードは少しずさんです。 これが適切に機能するようになったら、間違いなくクリーンアップします。

3 Answer


2


読み取り用と書き込み用の2つのOVERLAPPED構造が必要です。 また、パイプを閉じる場合はパイプごとに1つのイベントハンドルが必要であり、すべてを中止する(およびアプリケーションを閉じる)場合はもう1つのイベントが必要です。 すべてのパイプが現在関与しているすべての操作に対して1つのWaitForMultipleObjectsを使用するか、それぞれに1つのWFMOを持つ2つのスレッドで読み取りと書き込みを分離できます。 パイプを閉じる方が簡単なので、スレッドを1つだけ使用します(そうしないと、パイプハンドルで参照カウントを行い、参照カウントがゼロになった場合にのみ閉じる必要があります)。

1つのイベントを取得したらそれを処理し、処理したばかりのイベントの後に配列内にあったすべてのハンドルで0秒でWFMOを試行します。 これにより、パイプが枯渇することはありません。 0秒のWFMOが経過すると、最初から通常のWFMOを繰り返します。

高い同時実行性が必要な場合は、イベントを個別のスレッドで処理し、WFMOから現在処理中のハンドルを省略します。 ただし、すべてのハンドルの追跡は少し複雑になります。


1


「CreateNamedPipe」呼び出しで「PIPE_WAIT」の代わりに「PIPE_NOWAIT」を渡そうとしましたか? これにより、 ReadFile`と WriteFile`が非ブロッキングになります。

または、非同期IOを使用してみましたか? `FILE_FLAG_OVERLAPPED`フラグを渡しているので、これは動作するはずです。 試した場合、どのような問題に遭遇しましたか?


0


Linuxの世界では、1つのプログラムがwrite / fwrite呼び出しを介して名前付きパイプに書き込み、別のプログラムがread / fread()を介してそれを読み取ることができます。

名前付きパイプの完全パスは、読み取り/書き込み操作で使用する必要があります。