forkとexecのお話
Perl Hackers Hub: UNIXプログラミングの勘所を読もうと思ったが、
「複製」と言っても,全部の情報が複製されるわけではありません。プロセスのメモリイメージが複製される(注2)一方で,プロセスが開いている「オープンファイル記述」(open file description)(注3)は複製されません。forkのあとは,親プロセスと子プロセスの両者が,単一のオープンファイル記述を指す「ファイル記述子」(file descriptor)(注4)を持つことになります(図2)
...既によく分からない。基本を押さえねば。
実際にコード書いてみないと、(ボクは)身に付かないので当たり前の確認をいくつかやってみる。
メモリは複製される
my $foo = 'foo'; my $pid = fork; die $! unless ( defined $pid ); if ( $pid == 0 ) { $foo = 'bar'; sleep 3; print "child: $foo\n"; } else { wait; print "parent: $foo\n"; } child: bar parent: foo
メモリは複製される(=共有ではない)ので、同一変数を子プロセスで変更したとしても親には影響与えない。
execしてもpidは同じ
exec ( 'ps', $$ ); PID TT STAT TIME COMMAND 970 s002 R+ 0:00.01 ps 970
そもそもexecってそういうものだけど、PID同じだー。
環境変数はexecした時に継承される
$ENV{PAGER} = 'more'; exec qw/printenv PAGER/; more
これも当たり前かもしれないけど、execから別コマンドを実行する時、環境変数は継承されますねー。
オープンファイル記述は複製されない
aaa bbb ccc
「オープンファイル記述」がなんであるかはよくわかってないですが...こんな中身のファイルがあるとして
open( my $fh, '<', 'input.txt') or die $!; my $pid = fork; die $! unless ( defined $pid ); my $line; if ( $pid == 0 ) { $line = <$fh>; print "child:$line"; close $fh; exit; } #wait; $line = <$fh>; print "parent:$line"; close $fh;
の結果は、waitの有無で変わっちゃう。そういうことなんですね。
だいぶアタマがすっきりしてきました。
で、fork-execって何のためにあるんだろう?という疑問がアタマをよぎったので調べたところ、pipeと組み合わせるらしい。ということで、次はpipeを調べることにします。あとはfile descriptorもわかんないからこれも。
追記(2012/01/08)
file descriptorはforkで共有されずprocessごとに持つことになるけど、オープンファイル記述(offsetとか)は共有なので子と親のどちらで先に読み出すかで結果が変わるよ、ということでした。