我需要将一些数据写入child中的文件句柄。文件句柄是在分叉之前在父文件中创建的。这是因为我可以从父文件句柄中读取数据,因为fork保留文件句柄并锁定它们(如果有的话),在父和子之间共享。这是在Linux和Windows平台上共享父和子的数据。我能够在Linux中使用IPC :: Shareable进行数据共享,这在windows中不起作用,因为windows中没有semaphore.pm [windos不支持semaphore.pm],所以对于windows我试过Win32 :: MMF哪个崩溃了我的perl编译器。
因此,使用文件句柄方法,IO写入不会发生在子级中。请查看以下代码
use strict;
use warnings;
print "creating file\n";
open FH, ">testfile.txt" or die "cant open file: $!\n";
close FH;
my $pid = fork();
if ( $pid == 0 )
{
print "entering in to child and opening file for write\n";
open FH, ">>testfile.txt" or die "cant open file: $!\n";
print FH "dummy data\n";
print FH "dummy data\n";
print "child sleeping for 5 sec before exiting\n";
sleep 50;
exit;
}
else
{
print "entering the parent process\n";
open FH, "<testfile.txt" or die "cant open file: $!\n";
print <FH>;
print <FH>;
}
答案 0 :(得分:2)
父进程应至少等待一小段时间才能让孩子有时间写作。
use strict;
use warnings;
print "creating file\n";
open my $FH, ">", "testfile.txt" or die "cant open file: $!\n";
close $FH;
my $pid = fork();
if ( $pid == 0 ) {
print "entering in to child and opening file for write\n";
open my $FH, ">>", "testfile.txt" or die "cant open file: $!\n";
print $FH "dummy data\n";
print $FH "dummy data\n";
# print "child sleeping for 5 sec before exiting\n";
# sleep 50;
exit;
}
else {
sleep 1;
print "entering the parent process\n";
open my $FH, "<", "testfile.txt" or die "cant open file: $!\n";
print while <$FH>;
}
输出
creating file
entering in to child and opening file for write
entering the parent process
dummy data
dummy data
答案 1 :(得分:2)
感谢您帮我解决这个问题。我试图解决这个问题昨天发现了一个关于fork的有趣的事情,同时使用它与文件句柄在子和父之间共享数据,即我们可以使用以下代码解决问题,并且技巧是在fork之前和内部打开文件句柄child只是写入文件句柄而不重新打开它。以下是修改后的代码。
use strict;
use warnings;
use Fcntl qw(:flock SEEK_END);
print "creating file handle\n";
open my $FH, ">testfile.txt" or die "cant open file: $!\n";
#close FH;
my $pid = fork();
if ( $pid == 0 )
{
print "entering in to child and opening file for write\n";
#open FH, ">>testfile.txt" or die "cant open file: $!\n";
# Put a exclusive lock in the filehandle for dening access to any other process during this child process run
flock($FH, LOCK_EX) or die "Cannot lock testfile.txt - $!\n";
# and, in case someone appended while we were waiting...
seek($FH, 0, SEEK_END) or die "Cannot seek - $!\n";
# write data to temp file with exclusive lock on it
print $FH "dummy data\n";
print $FH "dummy data\n";
# remove the lock once writing is done
flock($FH, LOCK_UN) or die "Cannot unlock temp.txt - $!\n";
print "child sleeping for 5 sec before exiting\n";
sleep 2;
exit;
}
else
{
print "entering the parent process\n";
#flock(FH, LOCK_UN) or die "Cannot unlock temp.txt - $!\n";
sleep 3;
open $FH, "<testfile.txt" or die "cant open file: $!\n";
while (<$FH>){
print "$_\n";
}
}
答案 2 :(得分:0)
正如mpapec所说,你很容易受到竞争条件的影响,在这种情况下,父母在孩子读完之前从文件中读取。如果您打算让子进程缓慢生成输出并让父进程相对快速地处理它,那么父进程将经常读取文件末尾。您将需要了解如何使用seek
重置文件结束标记并等待更多输入:
# parent process, after fork
sleep 1; # give child time to create, write to file
open my $fh, '<', 'testfile.txt';
while (1) {
my $line = <$fh>;
if (defined($line)) {
print $line; # or process($line)
# another way (other than waitpid, see below) to see if the child is
# finished is to use some convention between parent and child,
# like having the child print "DONE!\n" as the last output it produces
last if $line eq "DONE!\n";
} else {
# parent is starved for input. Is the child finished or is it just slow?
use POSIX ':sys_wait_h';
my $wpid = waitpid $pid, &WNOHANG;
if ($wpid == $pid) {
# child process has exited
last;
} else {
# child is just slow. Clear the eof on $fh
sleep 1;
seek $fh, 0, 1;
}
}
}
close $fh;
您真正应该做的另一件事是在子进程中刷新输出。除非您非常快速地产生大量输出,否则输出将花费时间在缓冲区中并且父级无法访问:
if ( $pid == 0 ) {
print "entering in to child and opening file for write\n";
open my $fh, ">>", "testfile.txt" or die "cant open file: $!\n";
$fh->autoflush(1); # force OS to send output to disk right away
print $fh "dummy data\n";
print $fh "dummy data\n";
print "child sleeping for 5 sec before exiting\n";
sleep 5.0;
# print $fh "DONE!\n";
close $fh;
exit;
}
进程间通信非常棘手,但要非常强大。继续练习。