2011-06-30 30 views
1

下面是launchs 10個進程的腳本,每個寫100,000行到標準輸出,這是繼承自父:我如何在Perl禁用標準輸出重定向到文件緩衝?

#!/usr/bin/env perl 
# buffer.pl 
use 5.10.0; 
use strict; 
use warnings FATAL => "all"; 
use autodie; 

use Parallel::ForkManager; 
my $pm = Parallel::ForkManager->new(4); 

$|=1; # don't think this does anything with syswrite... 

# start 10 jobs which write 100,000 lines each 
for (1 .. 10) { 
    $pm->start and next; 

    for my $j (1 .. 100_000) { 
     syswrite(\*STDOUT,"$j\n"); 
    } 

    $pm->finish; 
} 
$pm->wait_all_children; 

如果我管到另一個進程,一切都很好..

$ perl buffering.pl | wc -l 
1000000 

但是,如果我管道到磁盤,系統寫入對方互斥。

$ perl buffering.pl > tmp.txt ; wc -l tmp.txt 
457584 tmp.txt 

更重要的是,如果我打開的子進程寫文件句柄,並直接寫入tmp.txt:

#!/usr/bin/env perl 
# buffering2.pl 
use 5.10.0; 
use strict; 
use warnings FATAL => "all"; 
use autodie; 

use Parallel::ForkManager; 
my $pm = Parallel::ForkManager->new(4); 

$|=1; 

for (1 .. 10) { 
    $pm->start and next; 
    open my $fh, '>', 'tmp.txt'; 

    for my $j (1 .. 100_000) { 
     syswrite($fh,"$j\n"); 
    } 
    close $fh; 

    $pm->finish; 
} 
$pm->wait_all_children; 

tmp.txt共有1,000,000行預期。

$ perl buffering2.pl; wc -l tmp.txt 
100000 tmp.txt 

因此,通過'>'重定向到磁盤有某種緩衝但重定向到一個進程不?這是怎麼回事?

回答

3

當您重定向整個Perl腳本,你得到一個文件描述符(當你做和perl的繼承作爲stdout由shell創建),這是dup倒是給每個孩子。當您在每個孩子明確open你會得到不同的文件描述符(不dup的原件)。你應該可以,如果你吊open my $fh, '>', 'tmp.txt'你的循環複製shell重定向情況。

管道的情況下工作,因爲你談論到管道,而不是一個文件,它沒有偏移概念可以在內核,因爲我上述不經意間共享。

+0

@cespinoza:我沒有注意到你的意見衝突與您的測試結果:與不同的文件(最後一種情況),你會得到100,000行(每個線程將覆蓋從一開始的文件,具有獨立的偏移遞增每個寫) 。不像上面「如預期」那樣說出1,000,000。如果您查看共享描述符大小寫(shell重定向),您將看到文件被損壞。在這種情況下,您可以提交另一個關於偏移量更新方面的問題:這需要一些研究。 –

相關問題