3

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

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

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

これがいくつかの擬似コードです

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を搭載したWindowsXPボックスでもかなりうまく機能します。ただし、Win32でネイティブに動作させる必要があります。

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

何か案は?

ありがとう!

4

2 に答える 2

6

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

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

動作するコードを確認したい場合は、_PyPopenをチェックしてください。

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

于 2008-10-31T17:52:15.053 に答える
0

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

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

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

于 2008-10-31T17:22:56.440 に答える