这是一个启动10个进程的脚本,每个进程向其STDOUT写入100,000行,该行继承自父进程:
#!/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
但如果我管道到磁盘,那么syswrites会互相破坏。
$ 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
通过'>'进行重定向磁盘有某种缓冲但重定向到进程不?这是什么交易?
答案 0 :(得分:3)
当你重定向整个perl脚本时,你得到一个文件描述符(当你执行> tmp.txt
时由shell创建并由perl继承为stdout
),每个文件描述符为dup
儿童。当您在每个子项中明确open
时,您将获得不同的文件描述符(而不是原始文件的dup
)。如果你将open my $fh, '>', 'tmp.txt'
提升出循环,你应该能够复制shell重定向案例。
管道工作正常,因为您正在与管道而不是文件进行通信,而且它没有偏移的概念,如上所述,它可能会无意中在内核中共享。