我使用管道通过传递一个文件描述符来读取函数的输出。要异步读取输出,我在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处理程序之前确保已从管道读取所有输出?
答案 0 :(得分:0)
要获取可读字节数,您可以使用ioctl
FIONREAD
,这不是非常便携。请参阅this question作为一个人为的例子。
您还可以使用poll,select和朋友测试要阅读的内容的可用性。
报告文件结束条件,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”特殊字节序列,以便读者知道何时停止。