Есть ли ограничение на количество файловых дескрипторов, которые я могу открыть в Perl? - PullRequest
2 голосов
/ 05 августа 2011

Я устанавливаю ссылку на хэш, содержащую дескрипторы файлов.

Четвертый столбец моего входного файла содержит поле идентификатора, которое я использую для именования адресата дескриптора файла:

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 ]

7 голосов
/ 06 августа 2011

Существует ограничение на количество открытых файлов на процесс на всех языках программирования.

На самом деле это ограничение, установленное операционной системой для предотвращения использования вредоносными (или поддельными) программами всех ресурсов системы, что может привести к зависанию ОС.

Если вы используете ОС Linux (не Mac), проверьте ulimit и /etc/security/limits.conf.

ulimit -n 2048

Это должно работать на большинстве дистрибутивов Linux.

Я не знаю конфигурацию для Mac (она отличается от Unix в данном конкретном случае) и / или Windows.


Edit:

Предел OS OS X определяется с помощью инструмента launchctl:

launchctl limit maxfiles 2048 unlimited
6 голосов
/ 06 августа 2011

Существует ограничение, установленное операционной системой. Обратите внимание, что все stdin / stdout / stderr считаются FD. По умолчанию предел FD в Linux составляет 1024 на процесс. Этот вопрос дает немного больше деталей.

Обратите внимание, что жесткое ограничение для большинства Linux, которые я использовал, составляет 1024. Проверьте /etc/security/limits.conf (путь может зависеть от вашего дистрибутива), чтобы увидеть, можете ли вы его увеличить.

Вы также можете переписать скрипт, чтобы он не требовал одновременного открытия всех этих файлов. Либо загрузите все данные, либо предоставьте механизм отложенной загрузки, чтобы загружать данные, когда они вам нужны, а затем закрывать файл.

...