如何在Perl中不阻塞地测试STDIN?

时间:2022-08-04 07:28:11

I'm writing my first Perl app -- an AOL Instant Messenger bot that talks to an Arduino microcontroller, which in turn controls a servo that will push the power button on our sysadmin's server, which freezes randomly every 28 hours or so.

我正在编写我的第一个Perl应用程序 - 一个与Arduino微控制器对话的AOL Instant Messenger机器人,后者又控制一个伺服器,它将按下我们系统管理员服务器上的电源按钮,该服务器每隔28小时随机冻结一次。

I've gotten all the hard stuff done, I'm just trying to add one last bit of code to break the main loop and log out of AIM when the user types 'quit'.

我已经完成了所有艰难的工作,我只是尝试添加最后一段代码来打破主循环并在用户输入“退出”时退出AIM。

The problem is, if I try to read from STDIN in the main program loop, it blocks the process until input is entered, essentially rendering the bot inactive. I've tried testing for EOF before reading, but no dice... EOF just always returns false.

问题是,如果我尝试在主程序循环中读取STDIN,它会阻止进程直到输入输入,实质上是使机器人无效。我在阅读之前尝试过测试EOF,但没有骰子... EOF总是返回false。

Here's below is some sample code I'm working with:

以下是我正在使用的一些示例代码:

while(1) {
    $oscar->do_one_loop();

# Poll to see if any arduino data is coming in over serial port
    my $char = $port->lookfor();

# If we get data from arduino, then print it
    if ($char) {
        print "" . $char ;
    }

    # reading STDIN blocks until input is received... AAARG!
    my $a = <STDIN>;
    print $a;
    if($a eq "exit" || $a eq "quit" || $a eq 'c' || $a eq 'q') {last;}
}

print "Signing off... ";

$oscar->signoff();
print "Done\n";
print "Closing serial port... ";
$port->close() || warn "close failed";
print "Done\n";

1 个解决方案

#1


18  

The Perl built-in is select(), which is a pass-through to the select() system call, but for sane people I recommend IO::Select.

Perl内置的是select(),它是select()系统调用的传递,但对于理智的人我推荐IO :: Select。

Code sample:

代码示例:

#!/usr/bin/perl

use IO::Select;

$s = IO::Select->new();
$s->add(\*STDIN);

while (++$i) {
  print "Hiya $i!\n";
  sleep(5);
  if ($s->can_read(.5)) {
    chomp($foo = <STDIN>);
    print "Got '$foo' from STDIN\n";
  }
}

#1


18  

The Perl built-in is select(), which is a pass-through to the select() system call, but for sane people I recommend IO::Select.

Perl内置的是select(),它是select()系统调用的传递,但对于理智的人我推荐IO :: Select。

Code sample:

代码示例:

#!/usr/bin/perl

use IO::Select;

$s = IO::Select->new();
$s->add(\*STDIN);

while (++$i) {
  print "Hiya $i!\n";
  sleep(5);
  if ($s->can_read(.5)) {
    chomp($foo = <STDIN>);
    print "Got '$foo' from STDIN\n";
  }
}