2011-08-05 10 views
1

ファイルハンドルを含むハッシュリファレンスを設定しています。Perlで開くことができるファイルハンドルの数に制限はありますか?

$ cut -f4 myFile | sort | uniq 
id-0001 
id-0002 
... 
:私は識別子のリストを取得するには、GNUコアユーティリティを使用し

col1 col2 col3 id-0008 col5 
col1 col2 col3 id-0002 col5 
col1 col2 col3 id-0001 col5 
col1 col2 col3 id-0001 col5 
col1 col2 col3 id-0007 col5 
... 
col1 col2 col3 id-0003 col5 

私の入力ファイルの4列目は、私はファイルハンドルの先に名前を付けるために使用してい識別子フィールドが含まれています

この列に1024以上の一意の識別子が存在する可能性があります。各識別子に対してファイルハンドルを開き、そのハンドルをハッシュ参照に入れる必要があります。

my $fhsRef; 
my $fileOfInterest = "/foo/bar/fileOfInterest.txt"; 

openFileHandles($fileOfInterest); 
closeFileHandles(); 

sub openFileHandles {                                                    
    my ($fn) = @_;                                                    

    print STDERR "getting set names... (this may take a few moments)\n";                                       
    my $resultStr = `cut -f4 $fn | sort | uniq`;                                         
    chomp($resultStr);                                                    
    my @setNames = split("\n", $resultStr);                                               

    foreach my $setName (@setNames) {                                                
     my $destDir = "$rootDir/$subDir/$setName"; if (! -d $destDir) { mkpath $destDir; }                                   
     my $destFn = "$destDir/coordinates.bed";                                             
     local *FILE;                                                    
     print STDERR "opening handle to: $destFn\n";                                            
     open (FILE, "> $destFn") or die "could not open handle to $destFn\n$!\n";                                     
     $fhsRef->{$setName}->{fh} = *FILE;                                               
     $fhsRef->{$setName}->{fn} = $destFn;                                              
    }                                                        
}                                                         

sub closeFileHandles {                                                    
    foreach my $setName (keys %{$fhsRef}) {                                               
     print STDERR "closing handle to: ".$fhsRef->{$setName}->{fn}."\n";                                       
     close $fhsRef->{$setName}->{fh};                                               
    }                                                        
}  

問題は、私のコードはid-1022の同等で死にかけているということです。

opening handle to: /foo/bar/baz/id-0001/coordinates.bed 
opening handle to: /foo/bar/baz/id-0002/coordinates.bed 
... 
opening handle to: /foo/bar/baz/id-1022/coordinates.bed 
could not open handle to /foo/bar/baz/id-1022/coordinates.bed 
0 
6144 at ./process.pl line 66. 

私はハッシュリファレンスで開くまたは保存できるファイルハンドルの数にPerlでの上限があります?他の場所で別のミスをしたことがありますか?

+2

Perlには制限はありませんが、あなたのOSは確かにそうです。 (1024、それはSTDIN + STDOUT + STDERR + 1021のようです)。制限は設定可能です。ちなみに、 '$!'ではなく '$!'を表示してください。 – ikegami

+0

あなたは正しく、誤ったタイプミスです。 –

+2

http://perldoc.perl.org/FileCache.html FileCacheは、オープンファイルのOS制限を超えることができる標準モジュールです。 – d5e5

答えて

6

すべてのプログラミング言語でプロセスあたりのオープンファイル数には制限があります。

これは実際には、悪質な(または偽の)プログラムがシステムのすべてのリソースを消費するのを防ぐために、オペレーティングシステムによって制限されているため、OSがフリーズする可能性があります。

Linuxベースの(Mac以外の)OSをご使用の場合は、ulimit/etc/security/limits.confをご確認ください。

ulimit -n 2048 

これはほとんどのLinuxディストリビューションで機能するはずです。

Macの設定(この特定の点ではUnixとは異なります)および/またはWindowsはわかりません。


編集:OSによって決められた制限があり

launchctl limit maxfiles 2048 unlimited 
+0

'ulimit -n 2048'を動かすことはやりました。どうもありがとう! –

+0

この種のトリッキーを行う前に、何千ものファイルを同時に開く必要があるかどうかを見直してください。 –

+0

ファイルハンドルの開閉に時間がかかります。すべてのハンドルを同時に開いたままにしておくことができれば、制限を超えないように常に開いたり閉じたりしている小さなハンドルプールを管理するコードを記述してデバッグする必要はありません。 –

5

:OS Xはlaunchctlツールを使用して定義され

制限OS。 stdin/stdout/stderrはすべてFDとしてカウントされることに注意してください。 LinuxでのデフォルトのFD制限は、プロセスごとに1024です。 This questionは少し詳細を提供します。

私が使用したほとんどのLinuxのハード制限は1024です。/etc/security/limits.conf(パスはあなたのディストリビューションによって異なる場合があります)を確認してください。

また、これらのファイルを一度に開く必要がないようにスクリプトを書き直すことを検討することもできます。すべてのデータをロードするか、レイジーローディングメカニズムを提供して、必要なときにデータをロードしてからファイルを閉じます。

+0

私はメモリに収まるサイズより大きなサイズのファイルを扱っています。そのアイデアは、一度に1行ずつファイルをストリームし、より小さなファイルの大きなセットに分割することです。ハンドルのプールを開いたままにしておくと、大きなファイルの各行を処理するときに、それぞれのファイルにすばやく書き込むことができます。 –

関連する問題