2

我编写了一个从串行端口读取数据的 Perl 脚本。

use Device::SerialPort;
$PortObj = new Device::SerialPort ($PortName, $quiet, $lockfile);
$PortObj->read_const_time( 500 ); # timeout waiting for data after 500ms
...

主循环尝试从串口读取数据:

while ( 1 ) {
  ( $count, $data ) = $PortObj->read( $frameLength );
  process_my_data( $data );
  do_something_entirely_different_that_needs_being_done;
}

但是我不想让 $PortObj->read 超时(这会消耗很多时间),而是希望能够测试缓冲区中是否有数据,这样我就可以加快循环速度:

while ( 1 ) {
  if ( test_serial_data_available ) { ( $count, $data ) = $PortObj->read( $frameLength ); }
  do_something_entirely_different_that_needs_being_done;
}

我可以测试串行缓冲区的数据可用性吗?

EDIT1:我今天早上一直在重写问题以使用串行设备作为文件句柄并且读取数据有效,但它仍然阻塞了循环。这可能会打开新的选项来检查缓冲区中的可用数据。在伪 Perl 中:

use Symbol qw( gensym );
my $handle = gensym();
my $PortObj = tie( *$handle, "Device::SerialPort", $PortName );

while ( 1 ) {
  my $frameData;
  if ( test_serial_data_available ) { my $readLength = read( $handle , $frameData , $frameLength ); }
  do_something_entirely_different_that_needs_being_done;
}

所以我的问题是:应该是什么test_serial_data_available样子?

4

1 回答 1

1

由于您有一个文件句柄,因此您可以使用select.

select将采用任意数量的文件描述符并等待其中一个变为“就绪”,其中就绪由 3 个集合中的哪个select包含文件句柄来定义。详情请参阅perldoc -f select

select接受一个超时,所以如果你给它一个超时 0,它就变成了一个轮询函数。所以这个函数会做你需要的:

sub poll {
    my ($fh) = @_;
    my $in = '';
    vec($in,fileno($fh),1) = 1;
    return select($in,undef,undef,0);
}

# ...

if ( poll($handle) ) { my $readLength = read( $handle , $frameData , $frameLength ); }
于 2012-04-28T12:29:20.710 回答