2017-05-17 4 views
0

ここでは、2つの子プロセス間で正しいパイプ処理を行う方法を理解しようとしています。私は単純に、あるLinuxコマンドの出力を別のLinuxコマンドに渡して、プログラムを正常に戻そうとしています。しかし、私は、フォークされている第二の子供がついてきて、親がこの子を永遠に待っていると推測しています。私はこのコードを長時間試していたので、なぜそれが固まっているのかを調べようとしていました。私はCシステムのプログラミングについてはまあまあですが、私は学びたいと思っています。このCコードで何が問題になっていますか?子供は帰っていないのですか?

誰もがプログラムが終了しない理由を知っていますか?

ご協力いただければ幸いです。

ありがとうございました。

#include <stdio.h> 
#include <stdlib.h> 
#include <signal.h> 
#include <sys/types.h> 
#include <unistd.h> 
#include <sys/wait.h> 
#include <sys/stat.h> 
#include <fcntl.h> 
int main() 
{ 
    char *a[2] = {"/bin/ls", NULL}; 
    char *b[2] = {"/bin/cat", NULL}; 
    char *envp[2] = {getenv("PATH"), NULL}; 
    int fd[2], status; 
    pipe(fd); 
    int old_std_out = dup(1); 
    int old_std_in = dup(0); 
    dup2(fd[1], 1); 
    int pid = fork(); 
    switch(pid) 
    { 
     case -1: 
      perror("Forkscrew"); 
      exit(1); 
      break; 
     case 0: 
      execve(a[0], a, envp); 
      exit(0); 
      break; 
     default: 
      waitpid(-1, &status, 0); 
      dup2(old_std_out, 1); 
      break; 
    } 
    dup2(fd[0], 0); 
    pid = fork(); 
    switch(pid) 
    { 
     case -1: 
      perror("Forkscrew"); 
      exit(1); 
      break; 
     case 0: 
      execve(b[0], b, envp); 
      exit(0); 
      break; 
     default: 
      waitpid(-1, &status, 0); 
      dup2(old_std_in, 0); 
      break; 
    } 
    printf("\n"); 
    return 0; 
} 
+0

2匹の猫を飼っていませんか?あなたはフォークし、その後両方のフォークを再びですか? –

+0

'ls'の出力がパイプバッファに収まらない場合はどうなると思いますか? – EOF

+0

@SamKuhmonen 2匹の猫を飼っていますか?多分?最初のものは配列aのexecと配列bの次のexecです。私はfork()が子と親を返すと思った。 – user3499524

答えて

2

プログラムに2つの潜在的なデッドロックがあります。

まず、最初の子(lswaitpid()ls終了するまで戻りません、その場合にパイプへの書き込みしようとするときにブロックすることができ、第二子(cat)が実行を開始するまでlsが終了しません、缶waitpid()が返されるまで起こらない。 =>デッドロック。

第2に、catは、書き込み終了のすべてのファイル記述子が閉じるまでstdinから読み取ります。親プロセスcatの両方に、書き込み終了のコピーがあります。catには、が明示的にはありません。。書き込み終了の唯一のコピーが(このデッドロックを回避するために)同じプロセス内にある場合、オペレーティングシステムによってはread()がブロックされないことがありますが、これは保証されません。どちらの方法でも、親プロセスはファイル記述子のコピーを保持し、パイプの書き込み終了を待機する子プロセスの子プロセスは親プロセスwaitpid()をデッドロックします。

は多くの場合、プログラムを簡素化することは、このような問題を解決します

#include <stdio.h> 
#include <stdlib.h> 
#include <signal.h> 
#include <sys/types.h> 
#include <unistd.h> 
#include <sys/wait.h> 
#include <sys/stat.h> 
#include <fcntl.h> 
int main() 
{ 
    char *a[2] = {"/bin/ls", NULL}; 
    char *b[2] = {"/bin/cat", NULL}; 
    char *envp[2] = {getenv("PATH"), NULL}; 
    int fd[2], status; 
    pipe(fd); 
    //int old_std_out = dup(1); /*No need to copy stdout...*/ 
    //int old_std_in = dup(0); /*...or stdin...*/ 
    //dup2(fd[1], 1);   /*...if you wait dup2()ing until you need to*/ 
    int pid = fork(); 
    switch(pid) 
    { 
     case -1: 
      perror("Forkscrew"); 
      exit(1); 
      //break; /*unreachable*/ 
     case 0: 
      dup2(fd[1], STDOUT_FILENO); /*NOW we dup2()*/ 
      close(fd[0]); /*no need to pass these file descriptors to...*/ 
      close(fd[1]); /*...a program that doesn't expect to have them open*/ 
      execve(a[0], a, envp); 
      exit(0); /*might want an error message*/ 
      //break; /*unreachable*/ 
     default: 
      //waitpid(-1, &status, 0); /*don't wait yet*/ 
      //dup2(old_std_out, 1); 
      close(fd[1]); /*we don't need this in the parent anymore*/ 
      break; 
    } 
    //dup2(fd[0], 0); /*not needed anymore*/ 
    pid = fork(); 
    switch(pid) 
    { 
     case -1: 
      perror("Forkscrew"); 
      /*might want to ensure the first child can terminate*/ 
      exit(1); 
      //break; /*unreachable*/ 
     case 0: 
      dup2(fd[0], STDIN_FILENO); 
      close(fd[0]); /*again, cat doesn't expect a fourth fd open*/ 
      execve(b[0], b, envp); 
      /*again, error message would be nice*/ 
      exit(0); 
      //break; 
     default: 
      //waitpid(-1, &status, 0); 
      //dup2(old_std_in, 0); 
      break; 
    } 
    waitpid(-1, &status, 0); /*don't wait until both children are created*/ 
    waitpid(-1, &status, 0); 
    printf("\n"); 
    return 0; 
} 

見ての通り、私は改善のための提案の数を残してきたが、これはすでにexecve()の仕事の無事を提供し、今で正常に動作する必要があります。

+0

もう一度お手伝いをして、何時間もの欲求不満を救ってください。 – user3499524

関連する問題