2011-08-05 107 views
1

我正在設置一個包含文件句柄的散列引用。我可以在Perl中打開的文件句柄的數量是否有限制?

我輸入文件的第四列包含了我使用來命名文件句柄的目的地標識符字段:

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 

我用GNU核心工具,以獲得標識符的列表:

$ cut -f4 myFile | sort | uniq 
id-0001 
id-0002 
... 

在這個列中可能有超過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不會強加限制,但是您的操作系統肯定會這樣做。 (1024,看起來似乎是STDIN + STDOUT + STDERR + 1021)。這個限制可以是可配置的。順便說一句,你應該打印'$!',而不是'$?'。 – ikegami

+0

你是對的,壞的錯字。 –

+2

http://perldoc.perl.org/FileCache.html FileCache是​​一個標準模塊,應該允許您超出打開文件的操作系統限制。 – d5e5

回答

6

所有編程語言中每個進程的打開文件數量是有限制的。

這實際上是操作系統爲防止惡意(或僞造)程序佔用系統所有資源而可能導致操作系統凍結的限制。

如果您使用的是基於Linux的(非Mac)操作系統,請查看ulimit/etc/security/limits.conf

ulimit -n 2048 

這應該適用於大多數Linux發行版。

我不知道Mac的配置(它在這個特定點上與Unix不同)和/或Windows。


編輯:

限OS OS X使用launchctl工具定義:

launchctl limit maxfiles 2048 unlimited 
+0

運行'ulimit -n 2048'確實有效。非常感謝! –

+0

在做這種欺騙之前,請重新思考你的方法,看看你是否真的需要同時打開數千個文件。 –

+0

打開和關閉文件句柄需要時間。如果我可以同時打開所有的句柄,那麼我不需要編寫和調試代碼來管理我經常打開和關閉以保持極限的更小的句柄池。 –

5

有一個OS強加的限制。請注意stdin/stdout/stderr都算作FD。 Linux上的默認FD限制是每個進程1024個。 This question提供了更多的細節。

請注意,我使用的大多數Linux的硬限制是1024.請檢查/etc/security/limits.conf(路徑可能取決於您的發行版)以查看是否可以增加它。

您也可以考慮重寫腳本,使其不需要一次打開所有這些文件。要麼加載所有數據,要麼提供延遲加載機制,以便在需要時加載數據,然後關閉文件。

+0

我正在處理的文件大小超過了我可以放入內存的大小。這個想法是一次一行地流過文件並將其分割成一大組小得多的文件。如果我打開一個處理池,我可以在處理較大文件的每一行時快速寫入每個處理。 –

相關問題