• 締切済み

プロセスの生成(fork)

haporunの回答

  • haporun
  • ベストアンサー率40% (230/562)
回答No.3

下記のお答え。 んんんと、それだと最後に作成されたプロセスで、forkの戻り値が0なので、ifを通らないままforを抜けて、何もしないプロセスになってしまうような・・・。 for(n = 0; n < 2; n++){ if(pid[n] = fork) break; } switch(n){ case文で0~3 (←3までであることに注意) } とすると、forループを抜けた時点で、 (1) nに0が入っている、親プロセス (2) nに1が入っている、(1)プロセスに作られた子プロセス (3) nに2が入っている、(2)プロセスに作られた子プロセス (4) nに3が入っている、(3)プロセスに作られた子プロセス ができます。 どういう経緯をたどるかというと、 (1) 親プロセスはn=0をセットし、forkの戻り値にIDが入るのでブレーク、forを抜けたあとのnは0。 (2) n=0のループでforkを呼び出した時点でプロセスが複製され、forkの戻り値が0なので、ブレークせずにnがインクリメントされn=1に。そしてforkを呼び出し、プロセスIDが返り、真なのでブレーク、forを抜けたあとのnが1。 (3) n=1のループでforkを呼び出した時点でプロセスが複製され、forkの戻り値が0なので、ブレークせずにnがインクリメントされn=2に。そしてforkを呼び出し、プロセスIDが返り、真なのでブレーク、forを抜けたあとのnが2。 (4) n=2のループでforkを呼び出した時点でプロセスが複製され、forkの戻り値が0なので、ブレークせずにnがインクリメントされn=3に。そしてn>2なのでループを抜け、forを抜けたあとのnが3。 というわけでforを抜けたあとswitchで判別するといいと思います。 これは自分でやったことであり、参考書とかを見たわけではないので、これが一番正しいとは言えないのですが、動作はしました、perl上ですが(笑)。 でもどの言語でも同じだと思います。 ちなみにperlではpid[n]には、あとのプロセスのIDは格納されません。 たとえばn=0のプロセスではpid[1]は入っていませんでした。 どうやら、複製されたプロセスで、変数は共有されていないようです。 もちろん、この部文はほかの言語でどうなるかわかりませんが。 if(!(pid[n]) = fork()) break; とすると、いちばん最初のプロセス(n=0)だけのpid[n]にすべてのプロセスIDが格納されました。 プロセスを作成するのは最初のプロセスだけですから。 長くなりました。 参考になれば嬉しいです。

shizuoka7
質問者

お礼

大変参考になりました。詳しく教えて頂いてありがとうございました。

関連するQ&A

  • forkについて

    fork文を使った問題について質問です。 #include <sys/types.h> #include <stdio.h> #include <stdlib.h> #include <unistd.h> int main() { pid_t pid1,pid2; if((pid1 = fork()) == 0) printf("I am a first child with pid = %d,My parent pid is %d.\n",getpid(),getppid()); else if(( pid2 = fork()) == 0) printf("I am a second child with pid = %d,My parent pid is %d.\n",getpid(),getppid()); else printf("I am a parent with pid = %d.\nMy first and second children are %d and %d.\n",getpid(),pid1,pid2); exit(EXIT_SUCCESS); } このようなプログラムが与えられました。 問題は 1.このプログラムを改造して、1つの親プロセスから100の子プロセスを順に生成するプログラムをつくるというものと 2.1つの親から子プロセスを生成し、その子プロセスの孫プロセスを生成するプログラムをつくれというものです。 1はfor文を使えばできそうなのですが、forkの基礎が出来ていないのでどうループを回せばよいか分かりません。 2もfork内でforkを実行すればできそうだと思ったのですがうまく動かず・・・。 どうか正しく動くようなプログラムを教えてください!お願いします。

  • プロセスの生成

    #include<stdio.h> #include <unistd.h> main(){ int i; printf("\t(%s)プロセスID.....%d\n","元",getpid()); printf("\t(%s)親プロセスID...%d\n","元",getppid()); if((i=fork())==0) { //子プロセスで実行する部分 printf("\t子プロセスでのfork()の値 : %d\n",i); printf("\t(%s)プロセスID.............%d\n","子",getpid()); printf("\t(%s)親プロセスID...........%d\n","子",getppid()); printf("子プロセスを終了します\n"); } else{//親プロセスで実行する部分 printf("\t親プロセスでのfork()の値 : %d\n",i); printf("\t(%s)プロセスID.............%d\n","親",getpid()); printf("\t(%s)親プロセスID...........%d\n","親",getppid()); printf("親プロセスを終了します\n"); } } fork関数の振る舞いについてです。 上記のプログラムをgccでコンパイルして実行した場合出力結果が /_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/ (元)プロセスID.....375 (元)親プロセスID...246 親プロセスでのfork()の値 : 376 子プロセスでのfork()の値 : 0 (子)プロセスID.............376 (子)親プロセスID...........375 子プロセスを終了します (親)プロセスID.............375 (親)親プロセスID...........246 親プロセスを終了します _/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/ という感じで出力されました。 fork関数がプロセスの複製を行っていることと、戻り値が0と376の2つであることはわかりました。 また子プロセスには0を親プロセスには376を返すこともわかりました。 感覚的にはif文の真である子プロセス側の記述文と偽である親プロセス側 の記述文が同時に実行されているのではないかと考えましたが 同時に実行されているのに printf("\t子プロセスでのfork()の値 : %d\n",i); printf("\t親プロセスでのfork()の値 : %d\n",i); で表示される値が違うのはなぜでしょうか。 i=fork()によって代入されているのはわかるのですが、 同時に実行されつつ何故2つの違う値をiは出力できるのかがわかりません。 また出力結果が _/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/ (元)プロセスID.....377 (元)親プロセスID...246 親プロセスでのfork()の値 : 378 (親)プロセスID.............377 (親)親プロセスID...........246 親プロセスを終了します 子プロセスでのfork()の値 : 0 (子)プロセスID.............378 (子)親プロセスID...........1 子プロセスを終了します _/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/ 子プロセスから見たときの親プロセスが1となっているのは何故でしょうか? 本来ならば377ではないでしょうか? わかりにくい説明ですいません。 よろしくお願いします。

  • forkで子が親を終了させるか?

    fork() によって作られた子プロセスが、親プロセスを終了させる場合があるでしょうか? 形としては良く見かけるもので次のようになっています。 pid_t pid = fork(); if (pid < 0) {  エラー処理  return; } else if (pid == 0) {  子の処理 ... (1)  _exit(0); } /* ここが実行されない場合がある */ return; (1)の箇所に sleep() を幾らか入れると再現しなくなります。 親子の関係で子が親へ影響を与えることがあるでしょうか?

  • fork()のpidとppid

    システムコールのfork()の勉強をしています。 fork()によって作られたプロセスのそれぞれのpidとppidを知りたいのですが頭がこんがらがってしまいました。 「forkシステムコールは親プロセスには作成された子プロセスのプロセスIDが、子プロセスには0が返る」とあったので以下のコードの場合 pid = fork(); if(pid == 0) printf("%s, child process\n", msg); else printf("%s, parent process\n", msg); 子のpidが0のためifが実行され、親はelseが実行される というところまで理解できたのですが このとき親のpidは子のID、子のpidは0なのでしょうか? 教科書の図(添付)を見ると親のpidは0で子、孫になるにつれてpidが大きくなっていてよくわからなくなってしまいました。 例えば以下のようなコードがあった場合、 pid_t pid; // メインプロセスのPIDは42 pid = fork(); // プロセスをPID=11で作成 if (pid == 0) { pid_t pid2 = fork(); // プロセスをPID=25で作成 if (pid2 == 0) { sleep(20); exit(0); } waitpid(pid2,NULL,0); exit(0); } else { pid_t pid3 = fork(); // プロセスをPID=89で作成 if (pid3 == 0) { sleep(10); printf("** ONE **\n"); exit(0); } pid_t pid4 = fork(); // プロセスをPID=123で作成 if (pid4 == 0) { sleep(30); printf("** TWO **\n"); exit(0); } } sleep(20); exit(0); それぞれのプロセスのpidとppidはどうなるのでしょうか? 説明がうまくできないのですが、 分かる方いましたら回答よろしくお願いします。

  • Perlのforkについて

    PerlでDBに格納するプログラムを作成しています。 パラレルで行ないたいためにforkを使っているのですが、 いまいちわかっていないのでご教授ください。 やりたいことはパラレルでのDB格納です。 親、子両方のプロセスが完了したら後続処理を行い、 0を戻したいのですが、下記の方法ですと、 子が終了したらprintしてからreturnしているようです。 このように、親子の処理が完了したら後続処理に移るようにするためには どうしたらよいのでしょうか? if ($pid = fork()) { #親プロセス insertDB(); wait; return 0; } else { insertDB(); } print"ここは最後に通したい"\n;

    • ベストアンサー
    • Perl
  • fork()2

    質問を途中で投稿してしまいました^^; 前質問はNo.945866 forkをしたときは子プロセスが生成されるのはわかるのですが、生成されたあとは、子プロセスからまず開始されるのでしょうか? if(fork() == 0){.....} else { .....} と if(fork() != 0){.....} else { .....} の両方の形で記述してもどちらも子プロセス側から走っていました。環境に依存するというわけではないのでしょうか?

  • 子プロセスと親プロセス

    ある本を読んでいると、以下のような問いにぶち当たり、プログラムの仕方がよくわからないのです。 自分でもいろいろ調べたのですが、わからないので質問させていただきます。 自分のプロセスIDと親のプロセスIDのプロセスIDを表示するコマンドshowpidを作り、showpidを子プロセスとして10回実行するプログラムを作りなさい。ただし、execを用いてshowpidを10回実行すること。 というものなのですが、自分のプロセスIDと親のプロセスIDの表示方法はわかったのですが、それをコマンドとして作り、子プロセスとして10回実行する方法がわからなくて困っております。。。 言語はc言語を使ってもらいたいです。以下に自分のプロセスIDと親のプロセスIDを表示するプログラムを付けときます。 #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <sys/types.h> #include <sys/wait.h> int main(){ pid_t pid; int status; if((pid=fork())==0) printf("I am a child with pid=%d. My parent pid is %d.\n",getpid(),getppid()); else{ wait(&status); exit(EXIT_SUCCESS); }

  • Windowsでのfork方法

    Windowsプログラムで、UNIXライクなマルチプロセス処理を書きたいのですが、 fork()が使えないようで、代替の方法がわかりません。 CreateProcess()というAPIはありますが、これは単に実行モジュールの呼び出し を行う関数で、UNIXのようなfork()でプロセスを分けるものでは ないようです。 子プロセス内部で、構築済みのDLLを複数ロードしたいのですが、 そのDLLはマルチスレッド対応になっていないため、 マルチスレッド処理はできません。 具体的にやりたいと思っていることをプログラム的に書くと、 およそ以下のような処理です。(UNIXでよくやる手法です) ----- 実行処理のメイン() {  int p_pid[128];  for(int i=0; i<10; i++) {   switch(pid[i]=fork()){    case 0: // 子プロセスとしての処理     子プロセスが呼び出す関数();     exit(0);    case -1:     break;    default:     break;   }  } } void 子プロセスが呼び出す関数() {  LoadLiblary() と GetProcAddress() で、DLLを動的にロードし、  DLL内のAPIを呼び出す。  DLLがマルチスレッド対応でなくても、この関数は各々が別プロセスとして  複数同時実行されるので、問題なく処理できるはず。 } ----- この処理は、Windowsでは無理なのでしょうか? もしできるなら、Windowsで用意されているランタイムライブラリかAPIを 教えていただけないでしょうか? よろしくお願いします。

  • Linuxで生成したプロセスに処理をさせるには?

    Linuxの学んでいる者です。 表題の件について、本を読んだり、ネットで検索したり したのですが、解決ができなかったため質問させて いただきました。 以下に例を挙げます。 1つのCファイルに、「main」と「A」と「B」という関数があるとします。 「main」関数にて、fork()で2つプロセスを生成し、一方のプロセスでは 「A」関数を実行し、もう一方では「B」という関数を実行させます。 「A」という関数は3秒ごとに「1,2,3,…」と数字を出力するもので、 「B」という関数は5秒ごとに「10、20、30、…」と数字を出力するものとします。 こういう場合に、プロセスに「A」や「B」の処理を実行させることができません。 exec関数でプロセスに別のプログラムを実行させることはできますが、 プログラムの実行ファイルのパスを指定して実行させるようなので、 この場合にはうまく使えません。 理解されている方には、本当に些細なことではあると思いますが、 私では解決にまで至らなかったので、ご教授いただければ幸いです。 よろしくお願いいたします。

  • 子プロセスのデータを親プロセスに渡す方法ってありますか。

    こんにちは。 C言語内でfork()関数を使い親と子を分け、子プロセス間で生成されたデータを親プロセス側に渡して処理したいと考えています。要は、プロセス間でデータのやり取りをpipe()関数かなにかで行いたいと思っています。 子プロセスがデータをテキストファイルでどこかに出力して、それを親プロセスが参照する、というテキストファイルを橋渡しにする原始的な方法があるにはあるのですがこれは最終手段にしたいと考えています。他に良いやり方があればご教授いただけないでしょうか。 以下はサンプルコードです。 #include<stdio.h> #include<stdlib.h> #include<string.h> #include<unistd.h> #include<errno.h> #include<signal.h> #include<sys/types.h> int main(){ FILE *fp,*fp2; int fd[2],a,i = 0; pid_t pid; pipe(fd); char buff[1024]; pid = fork(); sigignore(SIGCLD); //ちゃんと子が死ぬようにする if(pid == 0){ close(STDOUT_FILENO); //画面に出力されないようにする dup2(fd[1],STDOUT_FILENO); close(fd[0]); fp = popen("tcpdump","tcpdump","tcp[13] & 255 == 2",NULL); } else{ sleep(1); //一秒だけ子プロセスを起動 kill(pid,SIGTERM); wait(); //完全に子プロセスを殺す fp2 = popen("wc -l fpのファイルデータ","r"); for(i=0;i<3;i++){ a = fgetc(fp2); putc(a,stdout); }printf("\n"); return 0; } } プログラムの内容は、 tcpdumpで処理(子プロセス)した内容を、wc -l で「行数」のみ取得する(親プロセス)というものです。あくまで目標ですが・・。^^; お手数でしょうが、どうぞよろしくお願いします。