SIGIO到达文件描述符我没有设置它,当没有IO是可能的

我想在文件描述符上有可能发生I / O时收到信号。 当程序没有进行I / O操作时,程序需要做其他事情,所以使用select(2)不是一个选项。

当我运行下面的示例代码时,即使在stdin上没有数据时,它也会尽可能快地从处理程序中打印消息。 即使是更奇怪的是siginfo_t结构中报告的文件描述符因运行而异。 我只设置为stdin(fd 0); 为什么处理程序会报告任何其他值? 有时我看到0,有时看到1,大部分时间我看到“?”,表示0,1或2以外的值。

这是在OpenSUSE 12.3,Linux内核3.7.10-1.16,但我看到什么似乎在CentOS 6.4与它的股票内核相同的问题。

我在处理程序中使用写入,因为信号(7)表示它是可重入的,因此在信号处理程序中使用是合法的。 这也是为什么我不打印sinfo-> si_fd的值; snprintf不可重入。 有一段时间,我怀疑使用SIGIO的stdio库,这就是为什么示例程序中没有任何地方使用stdio调用的原因(除了可能在库函数err(3)中)。

感谢您花时间阅读我的代码。

#include <fcntl.h> #include <time.h> #include <string.h> #include <stdio.h> #include <signal.h> #include <unistd.h> #include <stdlib.h> #include <err.h> #include <errno.h> int needRead = 0; const unsigned int bufsize = 256; void handler(int sig, siginfo_t *sinfo, void *value) { char *cp; cp = "in handler. fd: "; write(2, cp, strlen(cp)); switch(sinfo->si_fd) { case 0: cp = "0\n"; break; case 1: cp = "1\n"; break; case 2: cp = "2\n"; break; default: cp = "?\n"; break; } write(2, cp, strlen(cp)); needRead = 1; } int main(int argc, char *argv[]) { struct sigaction act; unsigned int counter = 0; int flags; char *outp = "."; /* set up the signal handler for SIGIO */ act.sa_sigaction = handler; act.sa_flags = 0; act.sa_flags = SA_RESTART; sigemptyset(&act.sa_mask); if (sigaction(SIGIO, &act, NULL) == -1) err(1, "attempt to set up handler for SIGIO failed"); /* arrange to get the signal */ if (fcntl(0, F_SETOWN, getpid()) == -1) err(1, "fnctl to set F_SETOWN failed"); flags = fcntl(0, F_GETFL); if (flags >= 0 && fcntl(0, F_SETFL, flags | O_ASYNC ) == -1) err(1, "fnctl F_SETFL to set O_ASYNC failed"); while (1) { char in_buf[bufsize]; int nc; counter++; write(STDERR_FILENO, outp, strlen(outp)); if (needRead) { needRead = 0; if ((nc = read(STDIN_FILENO, in_buf, bufsize)) == -1) { err(1, "read from stdin failed"); } else { outp = "Read '"; write(STDERR_FILENO, outp, strlen(outp)); write(STDERR_FILENO, in_buf, nc); outp = "'\n"; write(STDERR_FILENO, outp, strlen(outp)); } } } return 0; } 

Solutions Collecting From Web of "SIGIO到达文件描述符我没有设置它,当没有IO是可能的"

啊,有趣。

简短的回答是,一个SIGIO多次到达stdin,因为stdin是可写的 ,另外,你的SIGIO交付没有完全正确的设置。

为什么si_fd显然不可靠?

首先,您需要在sa_flags指定SA_SIGINFO,然后才能安全地使用sa_sigaction处理程序。

其次,你需要#define _GNU_SOURCE和明确的F_SETSIG到SIGIO之前,Linux将为您填写si_fd (和si_band )。 有点傻,恕我直言,但事实如此。 没有这个,传递给si_fd的值就没有意义了,正如你发现的那样。

为什么SIGIO一遍又一遍地被传送?

我猜你的程序的stdin是从你调用的shell中继承的,我猜这是一个终端设备,是可写的。 正如fd 0将不断选择(2)可写,那么它会不断为您生成SIGIO。

无论如何, si_band都有答案。 启用F_SETSIG, #include <poll.h> ,然后检查si_band以获得POLLIN,POLLOUT等,以确定哪些I / O事件触发了信号。

真的,stdin是可写的?

是啊。 尝试这些比较:

 $ [ -w /dev/stdin ] && echo Yes, stdin is writeable Yes, stdin is writeable # Endless SIGIOs $ ./my-sigio-prog ^C # No SIGIO $ ./my-sigio-prog < /dev/null # Two SIGIOs, after a delay. One for line-buffered "foo\n" and one for EOF $ { sleep 3; echo foo; sleep 3; } | ./my-sigio-prog