• ベストアンサー

forkでプリント結果の違い

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

  • Perl
  • 回答数3
  • ありがとう数0

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

  • ベストアンサー
  • _kappe_
  • ベストアンサー率68% (1523/2217)
回答No.2

自分の環境でprint "&";を実行した場合は、何も出力されないままPerlが終了しました。 Perlのprintはバッファリングを行っており、改行の時点でバッファリングされた文字列がまとめて出力されるようになっています。 https://mikeda.hatenablog.com/entry/20090427/1240846816 https://mikeda.hatenablog.com/entry/20090503/1241365884 print "#$_[0]\n&";を実行すると"#$_[0]\n"までの部分は"\n"によって出力されますが、その後の"&"はバッファリングされたままになります。その"&"が最終的に出力されるかどうかはタイミングなどに依存します(ひどい)。 バッファリングをやめてprint実行後すぐに出力されるように設定するには、予め$|=1;を実行します。上でリンクした2つ目の記事を参照。

その他の回答 (2)

  • _kappe_
  • ベストアンサー率68% (1523/2217)
回答No.3

補足です。 改行無しのprintは出力されないことがあって、forkやwaitとは関係ないということを示すのが回答No.1の意図でしたが、Perlの実行環境によっても挙動が異なるようですね。

  • _kappe_
  • ベストアンサー率68% (1523/2217)
回答No.1

forkも何も無しで、下記の2つの実行結果を見比べてみてください。 print "&\n"; print "&";

OK_WAVE
質問者

補足

回答者様のサンプルは当たり前の値が返ってきました 質問文のwaitをコメントにすると期待する値が返ってきます

関連するQ&A

  • Perlのforkについて

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

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

  • 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()の挙動がいまいち良く分からないので質問させてください。 自分は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の例を元に下記のようなソースでバックグラウンドで処理 しようとしているんですが、処理が終わるまでブラウザがロックされて しまします。 $| = 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
  • execl+forkで起動したシェルの結果

    execl+forkでシェルを起動したとき、 起動したシェルから返ってくる結果はどうやってとれるのでしょうか。 ============== pid_t pid_c; if(pid_c == 0) { int ret = execl(shell,shell, id, NULL); if(ret != 0) { exit(1); } } else if (pid_c < 0) { exit(1); }

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

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

  • 「単純なシェル」について

    よく単純なシェルとして紹介されている下記のようなプログラム while (1) { type_prompt(); read_command(command, params); pid = fork(); if (pid < 0) { printf("Unable to fork\n"); continue; } if (pid != 0) { wait(&status); } else { execve(command, params, 0); } } これを実際にC言語のプログラムとして実行するには、このプログラムにどのような実装をくわえればよいのでしょうか。 またプログラム中のtype_prompt();とread_command(command, params);はそんな意味なのでしょうか。 教えてください。

  • forkの失敗???

    C++(UNIX)です。 以下のようなprogramをくみました。 comは自作のCシェルです。 ------------------- : pid_t ch_pid = fork(); cout << "ch_pid = " << ch_pid<< endl; int shell_ret = 0; int execl_ret = 0; int status = 0; if( ch_pid == 0) { cout << "execl(shell)" << endl; execl_ret = execl(com, com, NULL); cout << "execl ret = " << execl_ret << endl; } else if(ch_pid < 0) { cout << "fail to fork" << endl; cout << "errno = " << errno << endl; return 0; } waitpid(ch_pid, &shell_ret, 0); : ------------------ 実行したところ、 成功する[シェルが実行される]場合と、失敗する[シェルが実行されない]場合があります。 シェルが失敗するときはそれ以上先に進まず、固まってしまいます。(waitpidのせいだと思いますが。) 成功する場合のログ --------------- ch_pid = 12885 ch_pid = 0 execl(shell) : --------------- 失敗する場合のログ --------------- ch_pid = 12885 : --------------- forkに失敗していたら、"fail to fork"と表示されると思うので forkには失敗していないと思うのですが・・・。 なぜ、execlは実行されないのでしょうか。

  • fork()2

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