如何在关闭之前确保具有异步IO的管道上的所有输出都已完成

时间:2011-11-22 14:19:54

标签: c linux unix

我使用管道通过传递一个文件描述符来读取函数的输出。要异步读取输出,我在ASYNC NON BLOCKING模式下设置管道的“读取”端,并使用SIGACTION配置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);

问题是,如果省略sleep函数调用,我可以在输出完成之前关闭管道并禁用SIGIO处理程序。结果是应用程序因未处理的SIGIO信号而中止(消息“I / O可能”)。

如何在禁用SIGIO处理程序之前确保已从管道读取所有输出?

2 个答案:

答案 0 :(得分:0)

要获取可读字节数,您可以使用ioctl FIONREAD,这不是非常便携。请参阅this question作为一个人为的例子。

您还可以使用pollselect和朋友测试要阅读的内容的可用性。

报告文件结束条件,read返回0作为计数。

<强>补遗

根据read(2)系统调用手册页,read失败,错误为==:

   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.

答案 1 :(得分:-1)

我相信你无法知道管道中是否会有更多数据。因此,如果您控制写入管道的进程,则需要编写一个商定的“END-OF-DATA”特殊字节序列,以便读者知道何时停止。