Perlのforkについて

このQ&Aのポイント
  • Perlのforkを使用して、パラレルでDBに格納するプログラムを作成しています。しかし、forkについて理解が不十分であり、お知恵を拝借したいです。
  • パラレルでのDB格納のために、親子のプロセスが完了したら後続処理を行い、0を戻したいですが、現在の方法では子プロセスが終了した後にreturnしてしまいます。
  • 親子の処理が完了した後に後続処理に移るためには、どのようにすればよいでしょうか?
回答を見る
  • ベストアンサー

Perlのforkについて

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

  • Perl
  • 回答数1
  • ありがとう数4

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

  • ベストアンサー
  • shiren2
  • ベストアンサー率47% (139/295)
回答No.1

子プロセスはexitしてしまって構いません。 別プロセスなので、親には影響しません。 >パラレルでのDB格納です。 蛇足ですが、DB格納はデータベースハンドルをコピーすると異常事態にならないとも限らないので、個別に取得した方がいいですよ。 以下サンプルです。 インデントは全角スペースになっています。 ------------------------------------------------------- #!/usr/bin/perl use strict; if(fork){  print("parent hello\n");  wait; }else{  print("child hello\n");  sleep 3;  print("child exit\n");  exit; } print("parent finish\n"); ------------------------------------------------------- モジュールを使うと楽です。 #!/usr/bin/perl use strict; use Parallel::ForkManager; # 並行処理は四つ my $pm = Parallel::ForkManager->new(4); my @id = (1 .. 10); for(@id){  # 子の処理  $pm->start and next;  print("this is $_\n");  sleep 2;  $pm->finish; } # 親はただ待つ $pm->wait_all_children; print("parent finish\n");

kumifeb227
質問者

お礼

おかげ様で解決いたしました。 ありがとうございました。

関連するQ&A

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

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

  • IIS7.0でPerlのCGIにてバックグラウンド

    はじめまして、初心者の質問で恐縮ですが、以下の点を教えて欲しいです。 IIS7.0のWebサーバで、CGIプログラムをPerlで作っているのですが、forkした子プロセス で時間のかかるバックグラウンド処理を行って、親プロセスでWebブラウザに返す処理を しようとしていますがうまくいきません。重たい処理が終了するまでWebブラウザに応答 されません。(子プロセスの終了が終わるまで、親プロセスのHTML表示処理がWebブラ ウザに返答されません)通常、子プロセスでclose(STDOUT)で親プロセスのHTMLの 表示処理が出来ると思っていますが。。。 どのようにすれば良いか教えてもらえると幸いです。以下は参考のプログラムです。 よろしくお願いします。 $|=0; if ( $pid = fork){ #親プロセス &disp_html(); #HTMLを表示させるプログラム wait; }elsif (defined $pid) {  #子プロセス close(STDIN); close(STDOUT); close(STDERR); &heaby_prog(); #重たい時間のかかる処理 exit 0; } else { die "Can't fork: $\n"; } よろしくお願いします。

  • 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の並列処理

    私は今Perlの並列処理について学んでいます。3並列で子プロセスが行う処理はa1、a2、a3、・・・ak(処理にかかる時間a1<a2<a3<・・・)で、親プロセスはa1、a2、a3、・・・の結果を判定するというものです。 a1、a2、a3と順に判定していきたいと考えているのですが、どのようなプログラムを書けばよいでしょうか。なお、並列処理にはforkを利用するつもりです。 一度以下のようなプログラムを考えたのですが、これだとa1→a3→・・・→ak→親プロセス→a2→a4→・・・→a(k-1)→親プロセスとなってしまいます。よろしくお願いします。 while($count--){ #$countは並列数を入力   my $pid =fork;   &child_process;   exit; } wait; 【親プロセス】 sub child_process{   while($n<k){     $n=1;     【処理a$nを行う】     $n=$n+$count;     }   exit; }

  • 並列処理について

    今現在Perlの並列処理について勉強しているのですが、分からない点があるのでご教授願います。 重並列が可能となるプログラムを作りたいと思い、以下のプログラムを作成しました。countには並列数(例えば3並列にしたいならば3)が入っています。これで重並列ができたと思ったのですが、よくよく考えてみると、このプログラムだと一つ目の子プロセスが終わらなければ、二つ目、三つ目の子プロセスが始まらないということに気付きました。同時に複数のプロセスを実行させるにはどのようなプログラムにすればよいでしょうか。お願いします。 while($count--){ $pid = fork; if(!defined $pid){die "fork failed";} elsif(!$pid){ &process;#子プロセス exit; } } wait; ・・・・・・#親プロセス

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

  • forkしてもバックグラウンドで動かない

    お世話になっております。 あるサイトで見たforkの例を元に下記のようなソースでバックグラウンドで処理 しようとしているんですが、処理が終わるまでブラウザがロックされて しまします。 $| = 1; rm("-f","$TmpPath$KYOTEN/result/*.*"); &Upload_Check; print "Content-type: text/html\n\n"; &DataProgHeader_Write; #画面の切替 &DataProgDetail_Write; FORK: { if( $pid = fork ) { close(STDOUT); wait; } elsif (defined $pid) { close(STDOUT); chdir "/u1/uca/htdocs/PPro"; system("perl U0302.pl $Dkyoten"); exit; } elsif ( $! =~ /No more process/) { sleep 5; redo FORK; } else { &MsgDisp("Forkできませんでした。"); } } # End Of Label:FORK バックグラウンドで動かない理由が分からないのです。 どなたかお助けください。 また、ソース中で system("perl U0302.pl $Dkyoten"); とありますが、サーバで直に動かすと正常に動作するのですが cgiから呼び出すと文字コードエラーで落ちてしまします。 (呼び出すCGIはEUCで書いていますが、U0302.PLは処理の都合上 SJISで書いています。) こちらも原因の想定がつきません。 どなたか参考サイトでも構いませんので、お教えください。 お願いいたします。

    • ベストアンサー
    • Perl
  • 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でプリント結果の違い

    文末改行無しの動きがわかりません $pid = fork; if($pid){ Pid(1); wait; }else{ Pid(2); } sub Pid{ print"#$_[0]\n&"; #print"#$_[0]\n&\n"; }

    • ベストアンサー
    • Perl
  • プロセスの生成(fork)

    私はLinuxを始めたばかりのタコです。 参考書で少しずつ勉強しているのですが 「プロセスの生成にはforkを使用する」と記載されており プログラム例も載ってはいるのですが親プロセスと子プロセス一個の ケースしか記載されていません。 例にはPIDが0か0以外で親子を判断して別処理をさせると書いてありました。 例えば親プロセスと子プロセス2個以上を生成するにはどうしたらいいのでしょう?超ビギナーな質問で申し訳ありませんがタコを育てると思って どうか御教え下さい。宜しく御願いします。

専門家に質問してみよう