首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >Perl无法在子进程中写入文件句柄。

Perl无法在子进程中写入文件句柄。
EN

Stack Overflow用户
提问于 2013-11-06 10:45:39
回答 3查看 1.9K关注 0票数 5

我需要将一些数据写入子文件句柄中。文件句柄是在分叉之前在父文件中创建的。这是因为我可以从父文件句柄中读取数据,因为福克保留文件句柄和锁(如果有的话),在父和子之间共享。这是为了共享在linux和windows平台上工作的父级和子级的数据。我能够在linux中使用IPC::Shareable进行数据共享,这在windows中是行不通的,因为windows中的semaphore.pm不支持semaphore.pm,所以对于windows,我尝试了Win32 32::MMF,它破坏了我的perl编译器。

因此,使用文件句柄方法,IO写入不会发生在子程序中。请查看下面的代码

代码语言:javascript
运行
复制
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>;


}
EN

回答 3

Stack Overflow用户

发布于 2013-11-06 11:44:22

父进程应该等待至少一小部分秒,以便给子进程一些时间编写。

代码语言:javascript
运行
复制
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>;
}

输出

代码语言:javascript
运行
复制
creating file
entering in to child and opening file for write
entering the parent process
dummy data
dummy data
票数 2
EN

Stack Overflow用户

发布于 2013-11-07 06:47:41

谢谢你帮我解决这个问题。昨天我试图解决这个问题,并在使用它与文件句柄一起在子和父级之间共享数据时发现了一件有趣的事情,即我们可以用下面的代码解决这个问题,诀窍是打开文件句柄之前和里面的文件句柄,只需写到文件句柄,而不需要重新打开它。以下是修改后的代码。

代码语言:javascript
运行
复制
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
EN

Stack Overflow用户

发布于 2013-11-06 16:37:47

正如mpapec所述,您很容易受到一种竞争情况的影响,在此情况下,父程序在子文件读取文件之前从它读取。如果您打算让子进程缓慢地生成输出,并且父进程相对较快地处理它,那么父进程将经常在文件结束后读取。您将需要学习如何使用seek重置文件结束标记并等待更多输入:

代码语言:javascript
运行
复制
# 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;

您真正应该做的另一件事是在子进程中刷新输出。除非您非常快地生成大量输出,否则输出将花费时间在缓冲区中,并且父程序无法访问:

代码语言:javascript
运行
复制
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;
}

进程间的沟通是非常棘手的事情,但也非常强大。继续练习。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/19809999

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档