2013-02-19 10 views
6

私はOSに近いプログラミング手法に関与していませんが、私が知っているように、Perlで何かを並行して実行する場合、選択武器はforkであり、おそらくそれに基づいて構築された有用なモジュールです。 forkのdocページは言う:結果として独立して動作するコードの一部を切り離すPerlの技術とは何ですか?

Does a fork(2) system call to create a new process running the same program at the same point. 

を、大量のメモリを消費し、小さなタスクのためforkを呼び出すと、そこに2つの大きなperlのプロセスとなり、第二は、資源を無駄にすることを意味し、大きなアプリケーションを持ちますちょうど簡単な仕事をするだけです。

だから、質問は:(またはどのようにforkを使用することが唯一の方法だ場合、)それはを必要とするだけのリソースを消費独立して実行されているコードの取り外した部分を持つために何をすべきか?ただ非常にsimpel例

use strict; 
    use warnings; 

    my @big_array = (1 .. 2000000); # at least 80 MB memory 
    sleep 10; # to have time to inspect easely the memory usage 

    fork(); 
    sleep 10; # to have time to inspect easely the memory usage 

と子プロセスが消費80+ MBを過ぎます。

明確にする:このデタッチコードと通信することが重要ではないですかねえ、バックグラウンドでこの単純なタスク私のために実行」と言うと、私は私を継続させるためにだけ可能であることを、何とかその結果を使用します一方、重い作業...と重いperlアプリケーションを実行しているときに私のリソース! "を無駄にしないでください。

+0

子プロセスはすべての親の属性を継承します。私は思っていませんフォークでそれを回避するための実際の方法はありません。 – squiguy

+0

'fork'は必須ではありません。どんな手法でも、「システム」を呼び出すことさえ可能です。 – ArtM

答えて

3

fork()exec()はあなたのバニーです。新しいプロセスを作成するにはfork()(これはかなり安価な操作です、下記を参照してください)、次にexec()を使用して、実行している大きなperlをより小さなものに置き換えてください。これは、次のようになります。

use strict; 
use warnings; 
use 5.010; 

my @ary = (1 .. 10_000_000); 

if (my $pid = fork()) { 
    # parent 
    say "Forked $pid from $$; sleeping"; 
    sleep 1_000; 
} else { 
    # child 
    exec('perl -e sleep 1_000'); 
} 

@aryは少しだけ、元のプロセスのメモリを埋めるために使用されました。)

fork()は、元のプロセス全体をコピーしても、比較的安いと言いました。これらの声明は矛盾していません。 forkをデザインした人たちもこの同じ問題に気づいた。コピーは遅延です。つまり、実際に変更されたビットだけがコピーされます。

プロセスが互いに話をしたいと思えば、より複雑なIPCのドメインに入ることになります。これについては、いくつかの書籍が書かれています。

+0

'exec()'を呼び出す前に非常に短い時間だけメモリをコピーしておき、子プロセスが終了したらメモリを解放しますか?とにかく、すべてがcall system/execに収束すれば、forkを使う必要はありません:) 'exec'では必須ですが、' system( '... &'); 'はうまくやっているようです – ArtM

+2

@ArtM 'system( '...&')' *は 'fork()'とそれに続く 'exec()'です。 – darch

+1

Linuxの場合、PID> 1のすべてのプロセスは、fork(最初はinit)を使って作成されます。たとえば、実行すると – rjh

1

あり、あなたのプロセスのフットプリントのサブセットだけをフォークする方法はありませんので、通常の回避策はに降りてくる:あなたが親プロセスでメモリを大量にコードを実行する前に、

  1. fork
  2. は別のプロセスを開始
  3. systemまたはopen HANDLE,'|-',...である。もちろん、この新しいプロセスは親からのデータを継承しないため、この子に何らかの形でデータを渡す必要があります。
3

フォークされたプロセスでは、実際には80MBの常駐メモリが使用されていません。そのメモリの大部分は、共有となります。親プロセスまたは子プロセスが書き込みを行うまでは、コピーオンライトのセマンティクスによってメモリが実際にコピーされます。

荷物を完全に落としたい場合は、execをフォークで実行してください。これは、子供のPerlプロセスを別の実行可能ファイルに置き換え、メモリを解放します。親に何かを伝える必要がなければ、完璧です。

+0

字句変数が*共有*であるかどうかわかりません。 48m/1776と46m/156(1Mの配列要素)の両方のプロセスが実行されている間、これらの値は 'ps 'のRES/SHR列の下にあります。 – ArtM

+0

申し訳ありませんが、上記のコメントで 'ps'の代わりに' top'にする必要があります – ArtM

1

fork()ほとんどのオペレーティングシステムで実装されているように効率的です。一般的には、コピーオンライトと呼ばれる手法を使用します。これは、ページが最初に共有されることを意味します。また、あなたのプロセスメモリの多くは、とにかくマップされたファイルを読み込み専用にする予定です。

fork()の前に1つのプロセスが80MBを使用しているからといって、後で2つが160を使用するわけではありません。各プロセスがより多くのページをダーティーするまで、80MBを超えるわずかな割合になります。

+0

少なくとも1つのプロセスがダーティングを開始するまで*あるべきであると思う* *または同等の論理的に等価なものまあ、この 'my @big =(1 .. 1000000)'は単なる汎用的なコード例であり、より複雑で広がりのあるov全体のコード空間。あなたの介入に感謝します。 – ArtM

関連する問題