2012-09-28 36 views
4

我想使用O_ASYNC選項,並且當管道可以讀取時,SIGIO的處理程序將運行, 。如何在perl中使用O_ASYNC和fcntl?

但以下代碼不起作用。任何人都可以幫助我?

#!/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的

+0

FIFO上的O_ASYNC是否在C系統中工作? – pilcrow

+0

我寫了一個C版本,但它也沒有工作:你能給我一個C例子嗎? – Chinaxing

回答

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 
+0

爲什麼使用花哨的'「 - |」'參數而不是普通的管道打開?順便說一下,$$','順便說一下。 – tchrist

+0

@tchrist,re:'「 - |」',只是複製了OP的fanciness。 Re:'0 + $$',謝謝。 – pilcrow

+0

文件的默認擁有者是誰?不是誰打開它的過程? – Chinaxing

1

SIGIO基於異步IO是邊沿觸發,不是電平觸發。

在任何文件句柄將向您發送SIGIO之前,您必須先「武裝」它。爲此,您需要執行任何操作 - 在此情況下爲sysread() - 直到獲得undef/EAGAIN。此時,文件句柄現在將被配備爲SIGIO,並且在下次準備就緒時將發送一個信號。然後你可以閱讀它,直到它產生EAGAIN,這將再次武裝它。

+0

這個分析是錯誤的。如果我打開(F,' - |')'並讓孩子爲'('foo','bar'){說;睡2; } exit',除了O_ASYNC/F_SETOWN之外,父節點將獲得三個SIGIO而不對'F'做任何事情。 [Example here](http://pastebin.com/CyjGJtEA),也在內核2.6.18下。 – pilcrow

+0

你能舉個例子嗎?很感謝! – Chinaxing