2011-11-22 33 views
2

我使用管道通過傳遞文件描述符來讀取函數的輸出。要異步讀取輸出,我在ASYNC NON BLOCKING模式下設置管道的「讀」端,並使用SIGACTION配置一個IO處理程序。我的代碼如下所示:如何確保異步IO管道上的所有輸出在關閉之前完成

struct sigaction io_act; 
struct sigaction io_act_old; 
sigset_t block_mask; 

/* create the pipe */  
pipe (pipe_fd); 

/* set the reading end of pipe in ASYNC mode */ 
fcntl (pipe_fd[0], F_SETOWN, getpid()); 
fcntl (pipe_fd[0], F_SETFL, O_ASYNC | O_NONBLOCK); 

/* add an I/O handler for SIGIO */ 
sigemptyset (&block_mask); 
io_act.sa_handler = sigio_handler; 
io_act.sa_mask = block_mask; 
io_act.sa_flags = SA_RESTART; 
sigaction (SIGIO, &io_act, &io_act_old); 

/* executing the function that generate output in given FILEDES */ 
my_generate_output (pipe_fd[1]); 

close(pipe_fd[1]); 

/* this sleep should not be needed (subject of question) */ 
sleep(1); 
close (pipe_fd[0]); 

/* restore previous signal handler */ 
sigaction (SIGIO, &io_act_old, NULL); 

的問題是,如果我忽略了睡眠函數調用我可以關閉該管道,並完成了輸出前禁用SIGIO處理程序。其結果是應用程序由於未處理的SIGIO信號而中止(消息「可能的I/O」)。

在禁用SIGIO處理程序之前,如何確保所有輸出都已從管道中讀取?

+0

輸出到管? –

+0

我對此並不完全確定,但是你不能'F_SETOWN'爲0以防止信號? – Hasturkun

+0

aio_suspend()不會給你你想要的東西嗎? –

回答

0

要獲得可讀字節數,您可以使用ioctlFIONREAD,這不是非常便於攜帶。作爲一個人爲的例子,請參閱this question

你也可以用pollselect和朋友測試物品的可用性。

並且報告文件結束條件,read返回0作爲計數。

補遺

根據read(2)系統調用手冊頁,read失敗,並將errno ==:在一個單獨的過程中產生的或線程

EAGAIN or EWOULDBLOCK 
      The file descriptor fd refers to a socket and has been marked 
      nonblocking (O_NONBLOCK), and the read would block. 
      POSIX.1-2001 allows either error to be returned for this case, 
      and does not require these constants to have the same value, so 
      a portable application should check for both possibilities. 
+0

這不起作用。他的文件描述符被設置爲非阻塞,這意味着無法區分EOF和此刻無法讀取的內容。另外,'poll'和'select'不會阻塞非阻塞文件描述符。 –

+0

沒有可用的讀取給EWOULDBLOCK讀取-1,但EOF從讀取中給出0。如果沒有可用的數據,poll或select將不會報告爲可讀的非阻塞管道或套接字(我在幾年前嘗試過)。 –

+0

與FIONREAD的ioctl似乎很好,謝謝。我無法使用「讀取」方法,因爲我無法使用輸出。我不知道民意調查,我不熟悉它,我會研究手冊頁:-) – Francesco

-1

我相信你不知道管道中是否會有更多的數據。因此,如果您控制寫入管道的進程,則需要編寫一個商定的「數據結束」特殊字節序列,以便讀者知道何時停止。

+0

沒有辦法「沖洗」管道?畢竟我知道生成輸出的函數已經終止。 – Francesco

+0

調用投票(或者也許是ioctl FIONREAD)或者選擇測試東西是否可讀是永遠可能的。並且文件結束條件由'read'報告(作爲一個0字節計數) –

+0

根據'pipe(7)',如果寫入結束的所有文件描述符都已經關閉,'read()'會看到EOF並返回0.但是,由於你的'read()'調用是非阻塞的,我認爲目前沒有辦法區分EOF和沒有可用的數據。 –

相關問題