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)を指定する必要があります。したがって、例を機能させるには、例に1行追加するだけで済みます。

#!/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()を取得するまで、操作を実行する必要があります(この場合は) 。その時点で、ファイルハンドルは準備が整い、次の読み取り準備が整ったときにシグナルを送信します。その後、yield になるまでそれを読み取ることができます。これにより、もう一度準備が整います。undefEAGAINSIGIOEAGAIN

于 2012-09-30T17:10:36.453 に答える