2011-02-04 5 views
0
void doWork(){ 

    int fd[2]; 
    int pret = pipe(fd); 

    close(0); 
    close(1); 
    int dret = dup2(fd[1], 1); 
    close(fd[1]); 

    while(1){ 

    char buf[256]; 
    system("whoami"); 
    int rret = read(fd[0], buf, 256); 

    if(/* something interesting */){ 
     return; 
    } 
    } 
} 

int main(int argc, char* argv[]){ 

    int children = 2; 

    for(unsigned work = 0; work < children; ++work){ 

    pid_t pid = fork(); 

    if(pid == 0){ 
     doWork(); 
     break; 
    } 
    } 
    int status; 
    wait(&status); 

    return 0; 
} 

この例で何が問題になっていますか?私は、外部プログラムを呼び出すために各子プロセスを持っていて、パイプからそのプログラムの出力を読み込もうとしています。私のコードは、子供が1に設定されている場合にのみ機能します。並列フォークパイプ

EDIT:私はフォーク/パイプでタスク並列性を達成しようとしています。親プロセスと子プロセスの間に通信はありません。各子プロセスは外部プログラムを実行し、出力を読み込み、出力を処理し、目的の出力が見つかるまで続けます。

+0

何人かの子供には何が問題ですか?あなたはその行動を説明できますか? –

+0

私は前に言ったことを取り戻します。複数の子プロセスではうまく動作します。問題は、2つ以上の子プロセスでは、プログラムの処理時間が長くても非常に時間がかかりますが、1つの子プロセスでは数秒しかかかりません。私はSunOS 5.10で実行しています。多分それはそれと関係がありますか? – Arlen

答えて

6

fork()の前にパイプを作成する必要があります。あなたのコードでは、子プロセスだけがパイプを持ちます。それを共有するには、両方のプロセスが必要です。

例:。:

int fd[2]; 
pid_t pid; 

if (pipe(fd)) { /* TODO: handle error */ } 

pid = fork(); 
if (pid < 0) { /* TODO: handle error */ } 

if (pid == 0) 
{ 
    /* We are the child. Set fd[1] as stdout. */ 
    if (dup2(fd[1], 1)) { /* TODO: handle error */ } 

    /* Close fd[0]; this process doesn't need it. */ 
    close(fd[0]); 

    do_work(); 
    exit(0); 
} 
else 
{ 
    /* We are the parent... */ 
    /* Close the other guy's write fd. */ 
    close(fd[1]); 

    /* Now read from fd[0] */ 
    /* Possibly waitpid() on child pid, etc. */ 
} 

も:私は私fork()fflush(stdout);を呼びたいです。そうでなければ、printf()で奇妙な行動を観察します。

+0

子プロセスは 'fd [1]'をstdoutに複製した後にそれを必要としないので、それも閉じなければなりません。 – caf

+0

@caf - 同意します。しかし 'fd [0]'を閉じることは悪い結果を招くので、私はいつもそうしています。 'fd [0]'を閉じると、親が死んだ場合に 'fd [1]'に 'SIGPIPE'を書くことを意味します。しかし、あなたのプロセスで 'fd [0]'でこのような状況に陥ると、パイプのバッファがいっぱいになるとハングする可能性があります。 OTOH 'fd [1]'はプロセスの終了時に閉じてしまうため、オープンにしておくことは大したことではありません。 – asveikau

+0

申し訳ありませんが、それは役に立ちません。私はパイプとフォークでタスクの並列性を達成しようとしています。それぞれの子プロセスは 'system()'呼び出しを行います。その外部プログラムの出力はパイプにリダイレクトされ、パイプから読み込み、処理することができます。子どもは、「面白い」何かが起こるまでこのループを続けます。私のコードの問題は、複数の子プロセスが互いに干渉しているように見えることです。 – Arlen

1

子プロセスを実行し、コンテンツを解析し、解釈して終了する子を生成する必要がありますか?その場合は、作成するタスクごとにforkを2回入力する必要があります。最初にサブプロセスの結果を処理する子を作成し、2回目はサブプロセスを起動します。そのような

何か:

void ExecuteCommandAndInterpretResult(const char* command) 
{ 
    int fd[2]; 
    if (pipe(fd)) 
     exit(1); 

    pid_t pid = fork(); 
    if (pid < 0) 
     exit(1); 

    if (pid == 0) 
    { 
     if (dup2(fd[1], 1)) 
      exit(1); 

     close(fd[0]); 
     execl(command, basename(command), NULL); 
     exit(1); 
    } 
    else 
    { 
     int status; 

     close(fd[1]); 
     // do something with output from command 

     wait(&status); 
     exit(0); 
    } 
} 

#define CHILDREN 2 
int main() 
{ 
    unsigned int i; 
    pid_t pids[CHILDREN]; 

    for (i = 0; i < CHILDREN; i ++) 
    { 
     pids[i] = fork(); 
     if (pids[i] < 0) 
     { 
      // TODO: handle error 
     } 
     else if (pids[i] == 0) 
     { 
      ExecuteCommandAndInterpretResult("/usr/bin/ls"); 
      exit(0); 
     } 
    } 

    for (i = 0; i < CHILDREN; i ++) 
    { 
     if (pids[i] > 0) 
     { 
      int status; 
      waitpid(pids[0], &status, 0); 
     } 
    } 

    return 0; 
} 
0

あなたはwhoamiを実行するために、子供にpopen()を使用して検討していますか?