2011-05-24 82 views
5

在下面的代码中,我试图执行一个简单的文件尾部操作。假设foo.txt是完全空的。我期望第一个can_read()会阻塞,但它不会。 sysreadline()中的can_read调用也不会等待或等待。相反,第一个can_read会立即将​​句柄返回给foo.txt,并且sysreadline中的第一个can_read也会执行相同的操作。 sysread然后不返回任何内容,因为没有任何可读的内容,导致sysreadline内部忙于等待。怎么会这样?我知道select可以提前结束,因为信号或者关闭了文件句柄,但是在这里我没有看到任何机会。事实上,当文本在foo.txt中出现(用换行符)时,它将被打印。我不明白为什么代码在没有任何可读的情况下不会无限期地阻塞为第一个can_read。除了浪费cpu之外,它还使得无法同时拖放多个文件成为可能,因为在第一个忙碌的等待中你总会陷入困境。我觉得我必须忽视的东西简单在这里...perl can_read在没有东西可读时返回句柄

这是perl的5.8.8



#!/usr/bin/perl -w 
use strict; 
use IO::Select; 
use IO::Handle; 
use Symbol qw(qualify_to_ref); 

open my $inf, "<", "foo.txt" or die "hey! Can't open foo.txt!\n"; 
my $sel = IO::Select->new(); 
$sel->add($inf); 

while(my @ready = $sel->can_read()){ 

    foreach my $handle (@ready){ 
    my $line = sysreadline($handle); 
    print $line; 
    } 

} 

## 
## deal with buffering for select. from perl cookbook 7.23 
sub sysreadline { 
    my($handle, $timeout) = @_; 
    $handle = qualify_to_ref($handle, caller()); 
    my $infinitely_patient = (@_ == 1 || $timeout new(); 
    $selector->add($handle); 
    my $line = ""; 
SLEEP: 
    until (at_eol($line)) { 
     unless ($infinitely_patient) { 
      return $line if time() > ($start_time + $timeout); 
     } 
     # sleep only 1 second before checking again 
     next SLEEP unless $selector->can_read(1.0); 
INPUT_READY: 
     while ($selector->can_read(0.0)) { 
      my $was_blocking = $handle->blocking(0); 
CHAR:  while (sysread($handle, my $nextbyte, 1)) { 
       $line .= $nextbyte; 
     ##print "next: [$nextbyte]\n"; 
       last CHAR if $nextbyte eq "\n"; 
      } 
      $handle->blocking($was_blocking); 
      # if incomplete line, keep trying 
      next SLEEP unless at_eol($line); 
      last INPUT_READY; 
     } 
    } 
    return $line; 
} 
sub at_eol($) { $_[0] =~ /\n\z/ } 

+2

也许'File :: Tail'可以使用。 – TLP 2011-05-24 18:09:56

+0

你有'''而不是'<'在你打开。但是除此之外,我不确定非阻塞I/O对此有意义。管道/ FIFO或套接字可以处于连接状态,但正在等待更多数据。从常规文件中读取时,您可能处于最后或者不是。我不知道有什么方法让读者跟踪是否有其他人仍在写入文件。也许轮询'fstat()'? – Andy 2011-05-24 18:11:01

+0

@andy,这是在stackoverflow粘贴错误。我必须用一个实体替换原来的<或者它将被删除 – frankc 2011-05-24 18:16:17

回答

7

select返回装置“读不会阻塞(即永远等待一些外部事件发生)“,而不是”数据可用“。从磁盘读取文件永远不会阻塞,它会立即在EOF处返回0。

因此,您可能更喜欢使用@TLP建议的File::Tail

相关问题