#!/usr/local/bin/perl $mode = shift; if ( $mode eq 'flock' ){ } elsif ( $mode eq 'symlink' ){ $lockfile = "sym-lock"; unlink($lockfile); } elsif ( $mode eq 'mkdir' ){ $lockdir = "mkdir-lock"; rmdir($lockfile); } else { die "You must specify mode `flock', `symlink' or `mkdir'\n"; } $counter_file = "$mode.txt"; $countup_func = "countup_$mode"; open(F,">$counter_file"); print F "0\n"; close(F); $loop = shift || 1000; # カウントアップする数 $max_children = shift || 5; # 同時に生成する子供の数 $now_children = 0; # 現在の子供の数 for ( $x=0 ; $x<$loop ; $x++ ){ if ( $pid = fork() ){ # 親 $now_children++; } else { # 子 &$countup_func($x); exit; } if ( ! $pid ){ # fork できなかった die "Cannot fork! $!"; } if ( $now_children == $max_children ){ # 制限以上のプロセスを作らない wait; $now_children--; } } while ($now_children){ # 最後に残った子供たちを待つ wait; $now_children--; } open(F,$counter_file); # 結果表示 printf "Result ($counter_file) =%s",scalar(); close(F); exit; #--------------------- flock を使ったカウントアップ sub countup_flock { ($child_number) = @_; open(F, "+< $counter_file"); flock(F,2); $num=; seek(F, 0, 0); printf F "%d\n",$num+1; close(F); printf "$mode: I'm %dth child. counter=%d\n",$child_number+1,$num+1; } #---------------------- symlink を使ったカウントアップ sub countup_symlink { ($child_number) = @_; $lock_flg = 0; while (1){ $lock_flg = symlink("$$",$lockfile); last if ( $lock_flg ); select(undef,undef,undef,0.1); # 0.1 秒 sleep } open(F,"$counter_file"); $num=; close(F); open(F,">$counter_file"); printf F "%d\n",$num+1; close(F); printf "$mode: I'm %dth child. counter=%d\n",$child_number+1,$num+1; unlink($lockfile); } #-------------------- mkdir を使ったカウントアップ sub countup_mkdir { ($child_number) = @_; $lock_flg = 0; while (1){ $lock_flg = mkdir($lockdir,0777); last if ( $lock_flg ); select(undef,undef,undef,0.1); # 0.1 秒 sleep } open(F,"$counter_file"); $num=; close(F); open(F,">$counter_file"); printf F "%d\n",$num+1; close(F); printf "$mode: I'm %dth child. counter=%d\n",$child_number+1,$num+1; rmdir($lockdir); }