• ベストアンサー

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を実行すればできそうだと思ったのですがうまく動かず・・・。 どうか正しく動くようなプログラムを教えてください!お願いします。

質問者が選んだベストアンサー

  • ベストアンサー
noname#119918
noname#119918
回答No.2

ざっと書いてみました。 1. fork -> 親プロセス) 子プロセスの終了を待ち、再びfork -> 子プロセス) 自身のプロセスIDを表示し、直ちにexit 2. fork -> 親プロセス) 子プロセスの終了待ち -> 子プロセス) 再びfork、孫プロセスの終了を待ち、直ちにexit -> 孫プロセス) 直ちにexit 上のような流れのプログラムです。 #include <stdio.h> #include <stdlib.h> #include <sys/types.h> #include <sys/wait.h> #include <unistd.h> void problem1(void); /*問題1*/ void problem2(void); /*問題2*/ pid_t Fork(void); /*forkのエラーをトラップするラッパ関数*/ void Wait(int *status); /*waitのエラーをトラップするラッパ関数*/ int main(void) { problem1(); problem2(); return 0; } void problem1(void) { int i; pid_t pid; for(i=0 ; i<100 ; i++) { printf("loop %d\n" , i); pid = Fork(); if(pid == 0) /*child process*/ { printf("child %d\n" , getpid()); exit(EXIT_SUCCESS); } /*parent*/ Wait(NULL); /*wait for child*/ } } void problem2(void) { pid_t pid0; pid_t pid1; pid0 = Fork(); if(pid0 == 0) /*child*/ { printf("child.\n"); pid1 = Fork(); if(pid1 == 0) /*grand child*/ { printf("grand child.\n"); exit(EXIT_SUCCESS); } /*child*/ Wait(NULL); /*wait for grand child*/ exit(EXIT_SUCCESS); } /*parent*/ Wait(NULL); /*wait for child*/ } pid_t Fork(void) { pid_t pid = fork(); if(pid < 0) { perror("fork"); exit(EXIT_FAILURE); } return pid; } void Wait(int *status) { if(wait(status) < 0) { perror("wait"); exit(EXIT_FAILURE); } }

gachaa
質問者

お礼

教えていただいたプログラムを元につくってみたところうまく動きました! ありがとうございます! どうやらwaitを考えるのが足りなかったみたいなので勉強してきます。ありがとうございました。

その他の回答 (1)

  • sakusaker7
  • ベストアンサー率62% (800/1280)
回答No.1

> 1はfor文を使えばできそうなのですが、forkの基礎が出来ていないのでどうループを回せばよいか分かりません。 >2もfork内でforkを実行すればできそうだと思ったのですがうまく動かず・・・。 うまくいかなかったソースを出してみませんか?

gachaa
質問者

補足

/*1のソース*/ int main(){ pid_t pid[99]; int i; for(i=0;i<100;++i){ if((pid[i] = fork()) == 0) printf("I am a child with pid = %d,My parent pid is %d.\n",getpid(),getpid()); } } これでやったら無限ループしてしまいました。 かといって exit(EXIT_SUCCESS); を加えれば1回で止まってしまいます。 /*2のソース*/ if((pid1 = fork()) == 0) pid2 = fork(); printf("I am a child with pid = %d,My parent pid is %d.\n",getpid(),getppid()); exit(EXIT_SUCCESS); このようにしようとしたのですが、うまくいきませんでした。 printfも明らかにうまくいきそうにないですけど、どうすればよいか分からなくて・・・。 どうか上手く動くプログラムを教えてください。

関連するQ&A

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

    ある本を読んでいると、以下のような問いにぶち当たり、プログラムの仕方がよくわからないのです。 自分でもいろいろ調べたのですが、わからないので質問させていただきます。 自分のプロセス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); }

  • C言語 fork()について

    C言語 fork()について C言語でSystem Call fork()というものがあるそうで、まずは http://cai.int-univ.com/sugsi/Lecture/NetProg/chapter5/fork.html こちらのサイトの例をvisual studio 2008で実行させてみようと思ったのですが、以下のエラーが表示されてしまいました。 1>c:\users\user\documents\visual studio 2008\projects\project1\system call fork\system call fork\system call fork.cpp(3) : fatal error C1083: include ファイルを開けません。'unistd.h': No such file or directory ソースは以下のものです。 #include <stdio.h> #include <sys/types.h> #include <unistd.h> int main(void) { int pid; char msg[256]; sprintf(msg, "hello world"); //sprinf()でmsgにhello worldを格納する pid = fork(); if(pid == 0) printf("%s, child process\n", msg); else printf("%s, parent process\n", msg); return 0; } #include <unistd.h>について注意されていますが、これは何なのでしょうか? #include<stdio.h>ならprintf()などの基本的な関数を使うのに必要なものと覚えたので、 #include <unistd.h>もfork()を使うときに必要なものだろう程度に思っているのですが、どうすれば、まずこのプログラムが実行できるんでしょうか? No such file or directoryと書かれているぐらいですから、下準備としてこのプロジェクトが保存されている場所でtxtファイルか何かを準備しておく必要があるということですかね...

  • 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はどうなるのでしょうか? 説明がうまくできないのですが、 分かる方いましたら回答よろしくお願いします。

  • プロセスに関するプログラム

    UNIX系OSでのプロセスの動きを確認するプログラムを勉強しています。 コマンドライン引数で与えられた整数の数だけプロセスを作成するというもので、わからないことがありますので教えて頂けると幸いです。 質問の要点は 1.プロセスの番号がなぜ順番どおりに並ばないことがあるのか 2.どのような点からこのプログラムのプロセスの最大生成数を判定す  るのか という2点です。 parentIDが1のときはinitが親を引き継いでいることはわかっています。 どなたかご教授おねがいします。 下記にソースコードを載せておきます。 *** process.c *** #include <stdio.h> #include <stdlib.h> #include <unistd.h> int main(int argc, char *argv[]) { int np; int i; pid_t child_id; if(argc == 2) { fprintf(stderr, "<number of processes>\n"); exit(1); } np = atoi(argv[1]); for(i = 0; i < np; i++) if(child_id = fork()) break; printf("%d: process ID=%ld parent ID =%ld child ID=%ld\n", i , (long)getpid(), (long)getppid(), (long)child_id); return 0; }

  • fork()の挙動について質問させてください

    fork()の挙動がいまいち良く分からないので質問させてください。 自分はPHPでなのですが、fork()はCで使われるのが多いだろうということと、概念を知りたいとの事でこちらで質問させていただきました。 以下のように書きLinuxの端末にて実行しました。 目的は、 1. 2つの子プロセスを作り、それらを同時並行処理したい 2. 同時並行処理なので3秒後に処理を終わらせて出力したい という事です。 #!/usr/local/bin/php -q <?php $time = time(); $pid = pcntl_fork(); if ($pid == 0) { $j; for ($j=0; $j < 3; $j++) { printf("child1: %d\n", $j); sleep(1); } } else if($pid > 0) { pcntl_wait($status); print ("Parent-a\n"); } else { die('fork できません'); } $pid = pcntl_fork(); if ($pid == 0) { $i; for ($i=0; $i < 3; $i++) { printf("child2: %d\n", $i); sleep(1); } } else if($pid > 0) { pcntl_wait($status); print ("Parent-b\n"); } else { die('fork できません'); } echo "time:" . (time() - $time) . "sec\n"; すると、6秒後にまず child1: 0 child1: 1 child1: 2 child2: 0 child2: 1 child2: 2 time:6sec child1: 0 child1: 1 child1: 2 Parent-b time:6sec が出力され、その3秒後に Parent-a child2: 0 child2: 1 child2: 2 time:9sec Parent-a Parent-b time:9sec が出力されました。 分からない点は以下の通りです。 1. Parent-bがParent-aより前に表示されたり、 child1: 0 child1: 1 child1: 2 child2: 0 child2: 1 child2: 2 及びParent-a Parent-bを出力したいのに、 なんかそれ以外のものが色々と不思議な順序で出力されている上、 9秒も処理時間にかかり、並行処理ではなく逐次処理になっているように見える。 2. 確か"Unix/Linuxプログラミング理論と実践"だったと思うのですが、Unix系の本にて 子作成(親のコピー) -> 子処理中、親は居眠り -> 子exit() -> 親wait() -> 親起きる という感じで書かれていたように思いますが、 実行例のParent-a等を見ると、挙動が分かりません。 長くなり申し訳ございませんが、もし宜しければ間違っている点をご指摘していただけないでしょうか? また、上記に書いた"目的"を実現するためのCなどで宜しいですのでコード例など部分だけで宜しいですので挙げて頂けたら幸いです。 申し訳ございませんが、宜しくお願いいたします。

  • ファイルをオープンしたままfork

    ファイルをオープンしたままforkした際の動作について質問です。 下のコードを書いてコンパイル、実行します。 #include <stdio.h> int main(int argc, char **argv){ FILE *fp; fp=fopen("file", "w"); fprintf(fp, "%d\n", getpid()); printf("%d\n", getpid()); fork(); } ====== $ gcc hoge.c -o hoge.out $ ./hoge.out XXX ←pid なぜかファイル内には同じpidが2つ書かれている。 $ cat file XXX XXX fork()によって生成されたプロセスが元のプロセスのファイルを参照することは予想できます。 しかしforkする前にfprintしているのになぜまたファイルに同じ内容が書き込まれるのでしょうか?

  • マルチプロセスの動きについて教えてください

    例題として #include <sys/types.h> #include <unistd..h> #include <stdio.h> int main() { pid_t pid; char *message; int n; pid = pork(); switch( pid ) { case -1; perrorr( "forrk faaailed" ); exit(1); case 0; message = "This is the child"; n = 5; break; default : message = "This is the parent"; n = 3 break; } for( ; n > 0 ; n-- ){ puts(message); sleep(1); } exit(0) } のプログラムがあった場合結果が This is the parent This is the child This is the parent This is the child This is the parent This is the child $ This is the child This is the child となると本には書いてあります。 どうしてこのような結果になるのでしょうか。 forkとマルチタスクの動きがよく判りません。 どなたか、易しく教えていただけないでしょうか、 よろしくお願い致します。

  • UNIX times関数を用いた時間計測

    以下のようなforkを使用したプログラムの実行時間を計測したいのですが、times関数の使用方法がわかりません。 gettimeofdayを用いて物理的な実行時間を計測することは出来たのですが、 それでは不充分なので、もっと詳細に計測したいのです。 times関数を用いると ・実行中のプロセスが消費したユーザCPU時間 ・実行中のプロセスが消費したシステムCPU時間 ・子プロセスが消費したユーザCPU時間 ・子プロセスが消費したシステムCPU時間 がわかりますよね?sysconf()でクロック時間を得るところまでは出来たのですが、アドバイスお願いします。 #include <stdio.h> #include <sys/time.h> #include <sys/times.h> #include <unistd.h> int main(int argc, char *argv[]) { int val ; struct timeval tv,tw; gettimeofday(&tv,NULL); time = times(&t); switch(fork()) { case 0: exit(0) ; case -1: perror("child process") ; break; default: wait(&val) ; } gettimeofday(&tw,NULL); time = tw.tv_usec - tv.tv_usec; printf("child PID = %d\n",cpid); printf("val = %d\n"); printf("%ldus\n",time); }

  • プロセスの生成

    #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ではないでしょうか? わかりにくい説明ですいません。 よろしくお願いします。

  • perlのwhile loop内のforkについて

    perlのfork機能を使いたい者ですが、その挙動について質問しています。 ここ数日fork機能について勉強しましたが、 その挙動がどうでしても理解できないので、質問をさせていただいています。 質問内容を具体的にするため、以下に簡単なコードを書いておきます。 #!/usr/bin/perl use strict; my $i=0; while ($i<3) { if(fork()) { print("parent hello -> $i\n"); last; } else { print("child hello -> $i\n"); sleep 3; print("child exit -> $i\n"); $i++; } } print("parent finish\n"); このコードをlinux上で起動させますと、下記の結果が得られました。 parent hello -> 0 parent finish child hello -> 0 child exit -> 0 parent hello -> 1 parent finish child hello -> 1 child exit -> 1 parent hello -> 2 parent finish child hello -> 2 child exit -> 2 parent finish ここから質問です。 上記の結果の中で自分が理解できないのは、 なぜ、「parent finish」が4回も出てくるのかということです。 自分の理解している部分では、「parent finish」はwhile loopの外にあるので、 「parent finish」をプリントするには、一度while loopを出る必要があると思います。 しかし、それが2、3回と続いてプリントされていることがなぜなのか理解できません。 理想としては、 parent hello -> 0 child hello -> 0 child exit -> 0 parent hello -> 1 child hello -> 1 child exit -> 1 parent hello -> 2 child hello -> 2 child exit -> 2 parent finish という具合に、「parent finish」を一回だけ表示させたいのですが、それは可能でしょうか? ご教授をお願いします。よろしくお願いします。

    • ベストアンサー
    • Perl

専門家に質問してみよう