1

コマンドラインで数値を受け取り、 fork() を使用して数値の桁を合計する一連のプロセスを作成する小さなプログラムを作成しています。これまでのところ、次のとおりです。

#include <stdio.h>
#include <unistd.h>
#include <sys/wait.h>

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

  if(argc != 2){
    printf("Usage: sod [number] \n");  /* -o sod when compiled */
    exit(1); 
  }

  pid_t childpid = 0; 
  int sum = 0;   

  int i; 
  for(i = 0; i < strlen(argv[1]); i++){
    /* atoi needs a string */
    char str[2]; 
    str[0] = argv[1][i]; str[1] = 0;  
    sum += atoi(str);   
    if(childpid = fork()) 
      break;  
  }

  wait(NULL); 
  printf("sum: %d\n", sum);
  exit(0); /* probably redundant... */
  return 0; 
}

私のシステムブックで理解できることから、if ステートメントは、プロセスがチェーン内にあることを保証します (各親は 1 つの子を持つことができ、それは下に続きます)。これfork()は、子の ID を親プロセスに返し、0 を子。したがって、代入の結果は親に対して非ゼロ/真であり、強制的にループから抜け出します。

 if(childpid = fork()) 
          break; 

呼び出しを追加する前にwait(NULL)、関数は合計の複数行を出力しましたが、必ずしも順序どおりではありませんでした。これは、プロセスが異なる時間に終了するため、予想されるはずです。興味深いことに、11221121 のような桁数の多いプログラムを呼び出すと、合計の一部が出力され、その中間にシェル プロンプトが出力され、さらにいくつか出力されてから、まるで無限にあるかのようにそこにぶら下がります。ループ:

[nvj]@sun ~/313/sod> (12:15:21 02/10/13)
:: sod 11221121
sum: 1
sum: 2
sum: 4
sum: 6
sum: 7
sum: 8
sum: 10

[nvj]@sun ~/313/sod> (12:15:24 02/10/13)
:: sum: 11
sum: 11
[hangs here...]

なぜこれが起こっているのかについての私の唯一の推測は、何かがタイムアウトしているか、他の人を待つ必要があるものが轍になっているということです. プログラムを実際に終了させる (そして何らかの順序で合計を出力する) ために、wait(NULL)呼び出しを追加しました。私が理解していることから、続行する前に親がすべての子を待つ必要があります。当然のことながら、これにより、最後に作成された子が終了すると、実際の合計が最初に出力され、残りが順番に続きます。
[

nvj]@sun ~/313/sod> (12:25:02 02/10/13)
:: sod 12389492182398
sum: 69
sum: 69
sum: 61
sum: 52
sum: 49
sum: 47
sum: 39
sum: 38
sum: 36
sum: 27
sum: 23
sum: 14
sum: 6
sum: 3
sum: 1

ありがたいことに、この場合、プログラムは実際に終了します。しかし、実際の合計を持つ子が戻ってその結果を表示したときに、それを正しく終了させる方法はありますか? フラットアウト呼び出しなどを試してみましたがexit(ご覧のとおり...)、これは子プロセスとは異なる「領域」で動作しているようで、最初の印刷の直後には発生しません。

4

1 に答える 1

2

を使用fork()すると、数値の桁を合計するのにかなりコストがかかります。代わりに Web サービスを使用することもできます。それは遅くなります。

したがって、トレーニングの演習として、各子がそれぞれの変数の独自のコピーを持っていることを理解する必要があります。N 番目の子sumがその親プロセスの値に影響を与える方法はありません — 共有メモリなどに入らない限り.

あなたが言う時:

sum: 10

[nvj]@sun ~/313/sod> (12:15:24 02/10/13)
:: sum: 11
sum: 11
[hangs here...]

シェルは事前にプロンプ​​トを出して、あなたの入力を待っています。echo Hi「ハング」シェルで入力すると、エコーが表示され、プロンプトが通常どおり表示さHiれます。これは単に、最後の子プロセスが書き込みを完了する前に親プロセスが終了したことを意味します。

を挿入する前にwait()、最初のプロセスが分岐してループを終了し、その値を出力して終了し、シェルが再度プロンプトを表示できるようにしました。その間、最初の子は処理を行っており、2 番目の子は分岐と終了を行っていました。処理の順序はスケジューラによって決定されます。

適切wait()な場所で、子 (およびその子 (およびその子 (およびその子 ...))) は出力を完了し、決定論的な順序で回答が返されます。

最後の子には、前の子によって累積された数字の合計があります。つまり、最後の子だけが最終的な合計を取得するために何かを印刷する必要があります。

ステートメントの 1exit(0);つとreturn(0);冗長です。return(0);の代わりに を使用することをお勧めしexit(0);ます。

于 2013-02-10T18:37:59.153 に答える