2017-10-15 7 views
0

私は、ノードと呼ばれるパイプ経由で通信するプロセスからなるリンクリストを作成する必要があります。プログラムは、ルートプロセスとノード1という子プロセスから開始する必要があります。ユーザーには4つのオプションが与えられます。ノード1(プロセス)を追加できるオプション番号1に固執しています。子プロセスでパイプを読み取って、2番目の読み取りでハングする

ルートプロセスは、ユーザーの入力を要求する唯一のプロセスである必要があります。残りの部分は、読み込みブロックに当たるまでループし、書き込まれるのを待ちます。

ユーザが1を入力すると、プログラムは現在のプロセスが最後のノード(この場合はノード1)であるかどうかをチェックします。そうでない場合、プロセスは各フォークの前に作成されたパイプを介して入力を次のノードに書き込みます。そうであれば、プロセスはisLast変数をリセットし、新しいパイプと分岐を作成します。次に、子プロセス(ノード2)がループして、読まれた状態になってしまいます。親はその足跡をたどっています。ルートは再び使用入力を求めます。

問題は、プログラムが何の問題一度経由するとノード2を作成していないように見えるということですが、2回目では、ノード1は、ルートが

すべてのヘルプページの「ノードの追加」で、それへの書き込みを行うにもかかわらず、ハングアップ非常に高く評価されています!

#include <stdio.h> 
#include <unistd.h> 

int main(){ 
    int isLast = 0; 
    int originPID = getpid(); 
    int input = 0; 
    int node; 
    int p[2]; 

    //Node 1 
    printf("%s\n", "Forking"); 
    pipe(p); 
    int pid = fork(); 

    //Set Node 1 to last 
    if(pid == 0){ 
     isLast = 1; 
     node = 1; 
    } 

    while(input != 4){ 
     //Node Read Block 
     if(getpid() != originPID){ 
      printf("stuck\n"); 
      read(p[0], &input, sizeof(input)); 
      printf("free\n"); 
     } 

     //MENU (Root Only) 
     if(getpid() == originPID){  
      sleep(1); 
      printf("%s", "User Options: Enter a number \n1. Add Node\n2. List Processes\n3. Remove Node\n4. Quit\n"); 
      scanf("%d", &input); 
     } 

     //(1) Add Node 
     if(input == 1){ 
      //Checks if last. 
      if(isLast == 1){ 
       isLast = 0;  //Reset isLast 

       //Create pipe and new process 
       printf("%s\n", "Forking"); 
       pipe(p); 
       pid = fork(); 
       if(pid == 0){  
        isLast = 1; 
        node++;  //Label Node 
       } 
      } 
      //Write to next node 
      else{  
       write(p[1], &input, sizeof(input));  
      } 
     } 
    } 
} 
+1

これは永遠のループでは、例えば 'a 'と入力することで止めることができます。 'scanf("%d "、&input);'それから* never *は一致します。 'scanf'の戻り値をチェックし、引数が変換されなかった場合は、行末まで破棄しなければなりません。 –

+0

また、** ** **という行は何ですか、あなたの質問のコードと一致しません。あなたの質問の61はコメントです。また、[mcve]を読んで、これを同じ問題を呈する最小限のプログラムにしてください。 –

+0

@AnttiHaapala最初の答えは、ユーザーがプロンプトが表示されたら 'a'を入力すると、プログラムが永遠のループに入るということですか?教授が私たちに今適切なインプットを与えることを望んでいたので、私はまだその部分に触れていません。しかし、それは読み取りブロックにも影響しますか? – DazedFury

答えて

1

最後のノードがパイプから1を読み込むとき、作成しようとしている新しいノードと通信するための新しいパイプを作成する必要があります。私はそれがpipe(p)を呼び出す理由だと推測します。しかし、これは問題です。p[0]には、という独自のの入力を読み取るファイルハンドルの唯一のコピーが含まれているためです。次に入力を読み込もうとすると、次のノード用に設定したパイプからの読み込みを試みることになり、前身との接続が実質的に切断されます。

pipe()がそのファイルハンドルを書き込む配列については何も魔法はありません。ハンドルは単なる整数です。したがって、単純な解決策は、配列要素に格納された値を参照するのではなく、親が継承した読み込みファイル記述子のコピーを作成して使用することです。

また、フォークの後で、parentとchildはそれぞれ、使用しないパイプの最後のコピーを閉じます。 (親は読み込み終了を閉じ、子は書き込み終了を閉じます。)あなたはプログラムを使用せずに動作させることができるかもしれませんが、最低でもファイル記述子が漏れます。場合によっては、ファイルディスクリプタの余分なコピーを残すと、プログラムがハングアップすることがあります。

+0

答えを書く時間をとっていただきありがとうございます。申し訳ありませんが、子供にファイル記述子のコピーを作成させることによって、あなたは何を意味するのかを詳しく説明できますが、私はあまり理解していません。また、私たちの教授は、閉じられたファイル記述子がリサイクルされるので、この課題ではパイプを閉じないように教えてくれました。 – DazedFury

+0

@DazedFury、ファイル記述子は、配列要素自体ではなく、配列要素に格納された値です。同じ値を別の場所(つまり別の変数)に保存し、代わりにその変数を使用することができます。閉鎖に関しては、もしあなたの教授があなたにファイル記述子を閉じないように言ったら、当然あなたは彼らが言うようにすべきです。ファイル記述子番号を再利用できるのは正しいことです。しかし、それが問題を提起する理由がないとは思えません。 –

+0

それでした!素晴らしい仕事、助けてくれてありがとう。 – DazedFury

関連する問題