4

我想使用 O_ASYNC 选项,当管道可以读取时,SIGIO 的处理程序将运行。

但以下代码不起作用。任何人都可以帮助我吗?

#!/bin/env perl
use Fcntl;
 $SIG{IO}= sub {
   print "catch SIGIO!\n";
};

my $flags=0;

open(FH,"-|","sleep 4 ;echo aaa") or die "$!";

fcntl(FH,F_GETFL,$flags) or die "$!";
fcntl(FH,F_SETFL,$flags | O_NONBLOCK | O_ASYNC) or die "$!";

sleep(5);

print  "complete\n";

我的 perl 版本是 5.16.1,操作系统是 Redhat 5u4,内核 2.6.18,x86_64

4

2 回答 2

4

在 Linux 下,您必须同时请求异步通知 (O_ASYNC) 并指定接收者 (F_SETOWN)。因此,您只需在示例中添加一行即可使其工作:

#!/bin/env perl

use Fcntl;

$SIG{IO}= sub {
   print "catch SIGIO!\n";
};

my $flags=0;

open(FH,"-|","sleep 4 ;echo aaa") or die "$!";

fcntl(FH,F_GETFL,$flags) or die "$!";
fcntl(FH,F_SETFL,$flags | O_NONBLOCK | O_ASYNC) or die "$!";
fcntl(FH,F_SETOWN,0 + $$) or die "$!";  # <-- Note that we force $$ to be numeric

sleep(5);

print  "complete\n";

运行上述:

$ perl so-12640993.pl
catch SIGIO!
complete
于 2012-09-29T17:13:31.273 回答
1

SIGIO基于异步 IO 是边沿触发的,而不是电平触发的。

在任何文件句柄向您发送之前,SIGIO您必须先“武装”它。为此,您需要执行任何操作(sysread()在这种情况下),直到获得undef/ EAGAIN。此时,文件句柄现在将被武装起来,SIGIO并在下一次准备就绪时发送信号。然后,您可以阅读它,直到它产生EAGAIN,这将再次武装它。

于 2012-09-30T17:10:36.453 回答