2017-03-20 15 views
0

私は、特定のロジックを子プロセスに委譲する従来のコードを持っています。要件は、パイプへの親の書き込みと子がそれを読み込むことです。読んだ後、子供は新しいパイプに何かを書き、親はそこから読み込みます。双方向読み取り/書き込み用のパイプアクセスの同期

以下のコードでは、関数send()は親プロセスの専用スレッドによって定期的に呼び出されます。

LaunchWorker()は、子プロセスが最初の呼び出しでのみforkされるようにします。

1)2つのディスクリプタの読み込みと書き込みの終了方法を把握できないため、パイプに書き込まれた古いデータがすべての書き込みでフラッシュされます。 2)2つのディスクリプタにpipe()を2回呼び出すこともありますか?

このコードの作業を行うための入力は、非常に高く評価されます。 ありがとう!

typedef struct 
{ 
    WebClient* wc; // user defined class 
    string url; 
    string data; 
    size_t dataLen; 
    DownloadObserver* downloadCallback; // user defined class 
    string* token; 
}Payload; 

PayLoad pl; 

static pid_t worker_pid = 0; 
int fd1[2]; 
int fd2[2]; 

bool done = false; 

void LaunchWorker() 
{ 
    if (worker_pid != 0) 
    { 
     return; 
    } 
    pipe(fd1); 
    pipe(fd2); 

    worker_pid = fork(); 

} 

void send() 
{ 
    //populate pl; 

    LaunchWorker(); 

    if (worker_pid == 0) 
    { 
     while(true) 
     { 
      close(fd1[1]); 
      close(fd2[0]); 

      int cr = read(fd1[0], &pl, sizeof(Payload)); 
      if (cr > 0) 
      { 
       // Upload some data to a remote http endpoint - uses libcurl 
       //if upload success, done = true 

       int cw = write(fd2[1], &done, sizeof(bool)); 
       if (cw > 0) 
       { 
        // success 
       } 
       else 
       { 
        // failure 
       } 
      } 
      else 
      { 
       // failure 
      } 
     } 
    } 
    else if (workper_pid > 0) 
    { 
     close(fd1[0]); 
     close(fd2[1]); 
     int pw = write(fd1[1], &pl, sizeof(Payload)); 
     if (pw > 0) 
     { 
      int pr = read(fd2[0], &done, sizeof(bool)); 
      if (pr > 0) 
      { 
       // do something with value read 
      } 
      else 
      { 
       // failure 
      } 
     } 
     else 
     { 
      failure 
     } 
    } 
} 
+1

はい、2つのパイプを作成するには、 'pipe'を2回呼び出す必要があります。これは、パイプが一方向であり、一方向のみであるためです。 –

+0

ありがとうございます。私の最初の質問に関して、コード内でclose()を呼び出すべきであるどのようなヒントがありますか? – user2930006

+0

各プロセスで使用しない記述子(例えば、子プロセスでは 'fd1 [1]')を閉じる必要があります。それ以外のパイプ記述子を閉じる必要はありません。どのような「同期」が必要なのかよく分かりません。大量のデータを送信していますか? 'Payload'のサイズは? –

答えて

0

まず、あなたはすぐにフォーク後にパイプの未使用の端を閉鎖する必要があるので、親がFD1の読み出し側とFD2の書き込み終了を閉じる必要がありますし、子供が書き込み終了を閉じる必要がありますfd1とfd2の読み込み終了を示します。これをしないと、終了時にパイプは閉じられません。

次に、すべてを停止したいときは、パイプの書き込み側を書き込み側に近づけるようにします。すなわち

  • 親が
  • 子供がFD1にEOFを読み取り、それが
  • 子供が
  • 親がFD2にEOFを読み取り、それを閉じFD2の書き込み側を閉じ閉じFD1の終わりを書き閉じます。

子供がシャットダウンを開始する場合は、逆も同様です。

最後に、親プロセスは、waitシステムコールを発行して、子プロセスの終了結果を収集する必要があります。

はい、2本のパイプが必要です。パイプは1つの方法です。

+0

ありがとうございます。上記のコードを編集して、少なくとも1)2つのプロセスで不要な記述子を閉じる2)Payload構造体の定義。私が現時点で目にしている問題は、最初の書き込み/読み込み時にすべてうまく動作することです。 2回目の書き込みも良いです。plは期待値を持っています。しかし、2回目の読み込み後、plをチェックすると、pl.urlには同じ値が表示されます。 2番目(以降)の読み込みで何がうまくいかないのでしょうか? sizeof(ペイロード)80バイト。 – user2930006

+0

子供のread()の直前に、私はplのためにメモリも割り当てます。 'ペイロード* pl =(ペイロード*)malloc(sizeof(ペイロード));' 2回目の読み込みのサイズも正しい - 80バイト。しかし、私はまだ読むことができない2番目の読み取りを取得します。上記と同じ問題。 – user2930006

+0

@ user2930006この質問を編集して変更するのではなく、新しい質問を作成する必要があります – JeremyP

関連する問題