how to use O_ASYNC and fcntl in perl?

心不动则不痛 提交于 2019-12-23 12:41:39

问题


i want to use O_ASYNC option and when the pipe can read , the SIGIO's handler will run .

but the following code are not work . any one can help me ?

#!/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";

my perl version is 5.16.1 , operation system is Redhat 5u4 ,kernel 2.6.18, x86_64


回答1:


Under Linux, you must both request asynchronous notification (O_ASYNC) and specify a recipient (F_SETOWN). So, you need only add one line to your example to make it work:

#!/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";

Running the above:

$ perl so-12640993.pl
catch SIGIO!
complete



回答2:


SIGIO based asynchronous IO is edge-triggered, not level triggered.

Before any filehandle will send you a SIGIO you must first "arm" it. To do that, you need to perform whatever is the operation - sysread() in this case - until you get an undef/EAGAIN. At that point the filehandle will now be armed for SIGIO and will send a signal when it is next read-ready. You can then read it until it yields EAGAIN, which will arm it once more.



来源:https://stackoverflow.com/questions/12640993/how-to-use-o-async-and-fcntl-in-perl

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!