質問

私は比較的簡単だと思っていたプロジェクトを持っていますが、私が望んでいたより多くの苦痛であることが判明しました。まず、私がやり取りしているコードのほとんどは、私が制御できないレガシーコードであるため、大きなパラダイムの変更はできません。

ここで、私が何をする必要があるかを簡単に説明します。たとえば、stdinから読み取り、stdoutに書き込む簡単なプログラムがたくさんあるとします。 (これらに触れることはできません)。基本的に、stdinへの入力は、「Set temperature to 100」などのコマンドです。またはそのようなもの。出力は、「温度が100に設定されました」というイベントです。または「温度が設定値を下回りました」。

私がやりたいのは、これらの単純なプログラムの束を開始し、イベントを監視し、必要に応じてコマンドを送信できるアプリケーションを作成することです。私の最初の計画はpopenのようなものにすることでしたが、読み取りパイプと書き込みパイプの両方を取得するには、双方向補正のpopenが必要です。私はpopen2を呼び出す何かを一緒にハックし、そこで実行するコマンドと、読み取りおよび書き込みストリームで満たされる2つのFILE *を渡します。その後、必要なのは、各プロセスの各標準出力から読み取り、必要なロジックを実行し、適切なプロセスにコマンドを書き戻す単純なループを作成することだけです。

ここにいくつかの擬似コードがあります

FILE *p1read, *p1write;
FILE *p2read, *p2write;
FILE *p3read, *p3write;

//start each command, attach to stdin and stdout
popen2("process1",&p1read,&p1write);
popen2("process2",&p2read,&p2write);
popen2("process3",&p3read,&p3write);

while (1)
{
   //read status from each process
   char status1[1024];
   char status2[1024];
   char status3[1024];
   fread(status1,1024,p1read);
   fread(status2,1024,p2read);
   fread(status3,1024,p3read);

   char command1[1024];
   char command2[1024];
   char command3[1024];
   //do some logic here

   //write command back to each process
   fwrite(command1,p1write);
   fwrite(command2,p2write);
   fwrite(command3,p3write);
}

実際のプログラムはより複雑で、ストリームを覗いて何かが待機しているかどうかを確認し、そうでない場合はそのプロセスをスキップします。特定のプロセスにコマンドを送信する必要がない場合も同様です。 。しかし、このコードは基本的な考え方を示しています。

今、これは私のUNIXボックスでうまく機能し、cygwinを備えたWindows XPボックスでもかなりうまく機能します。ただし、Win32でネイティブに動作するようにする必要があります。

難しいのは、popen2がfork()とexecl()を使用してプロセスを開始し、子プロセスのstdinとstdoutにストリームを割り当てることです。 Windowsでこれを行うことができるきれいな方法はありますか?基本的には、Unixバージョンと同じようにWindowsで機能するpopen2を作成します。この方法では、Windows固有のコードのみがその関数内にあり、他のすべてが同じように機能することを回避できます。

アイデアはありますか

ありがとう!

役に立ちましたか?

解決

Windowsでは、最初にCreatePipeを呼び出し(pipe(2)と同様)、次にCreateProcessを呼び出します。ここでのコツは、CreateProcessには、新しく作成されたプロセスのstdin、stdout、stderrを渡すことができるパラメーターがあることです。

stdioを使用する場合、fdopenを実行してファイルオブジェクトを作成する必要があることに注意してください。ファイル番号が必要です。 Microsoft CRTでは、ファイル番号はOSファイルハンドルとは異なります。そのため、CreatePipeのもう一方の端を呼び出し元に返すには、最初に_open_osfhandleがCRTファイル番号を取得し、次にfdopenが必要です。

動作中のコードを見たい場合は、_PyPopen inをチェックしてください

http://svn.python.org /view/python/trunk/Modules/posixmodule.c?view=markup

他のヒント

クロスプラットフォームの問題を抽象化するためにpopen2()関数を使用することで、問題を非常にうまく開始できたと思います。私は来て「ソケット」を提案することを期待していましたが、質問を読んだ後、それは関係がないと確信しています。パイプの代わりにソケットを使用できます-popen2()関数で非表示になります。

Windows APIを使用して、必要な機能をWindowsに実装できることを99%確信しています。私ができないことは、正しい機能を確実に指すことです。ただし、MicrosoftにはPOSIXに似たAPI呼び出しのほとんどが用意されていますが、名前の先頭に「_」が付いていることに注意してください。 fork および exec の効果を実現するネイティブAPI呼び出しもあります。

コメントは、データの可用性とデッドロックの可能性に関する問題を認識していることを示唆しています。注意してください。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top