我正在为一个嵌入式Linux系统编写用户应用程序,使用了诸如open、close、read、ioctl等设备的常见函数。现在,我读到了关于EINTR的内容,它表示该函数被信号中断。但是我不确定这会产生什么影响。在我所有的示例程序中,有时候会这样做,例如ioctl(),有时候不会这样做,例如read()。所以,我有点困惑。
在什么情况下最好检查EINTR并重复函数调用?
我正在为一个嵌入式Linux系统编写用户应用程序,使用了诸如open、close、read、ioctl等设备的常见函数。现在,我读到了关于EINTR的内容,它表示该函数被信号中断。但是我不确定这会产生什么影响。在我所有的示例程序中,有时候会这样做,例如ioctl(),有时候不会这样做,例如read()。所以,我有点困惑。
在什么情况下最好检查EINTR并重复函数调用?
参见sigaction:http://pubs.opengroup.org/onlinepubs/009695399/functions/sigaction.html
SA_RESTART
This flag affects the behavior of interruptible functions; that is, those
specified to fail with errno set to EINTR. If set, and a function specified
as interruptible is interrupted by this signal, the function shall restart
and shall not fail with EINTR unless otherwise specified. If the flag is not
set, interruptible functions interrupted by this signal shall fail with errno
set to EINTR.
默认情况下,您具有SA_RESTART行为,因此如果您不处理信号,就不必担心EINTR问题。
signal(7)
以获取明确的针对Linux的信息。 - tneselect
和poll
之外,EINTR
只有在您安装(无论是出于错误/不理解如何使用sigaction
,还是因为您希望能够中断阻塞操作)中断信号处理程序时才会发生。当函数失败并出现EINTR
时重试循环只会撤消它。这是80年代和90年代初至中期许多操作系统存在缺陷且据称在非符合情况下产生EINTR
的旧反模式,但这些错误已经不存在了。EINTR
视为错误条件并在未完成操作的情况下返回到调用者。在这种情况下,安装重试循环可能是有意义的,但最好在操作期间屏蔽信号(至少是潜在中断的信号),并在完成后取消屏蔽。EINTR
仅在“该函数被信号中断”或类似情况下指定,其中 interrupted 的定义仅适用于非 SA_RESTART
信号处理程序。然而,对于 poll
函数而言,它被定义为“在 poll()
过程中捕获到一个信号”,无论该信号是否是中断信号。 - R.. GitHub STOP HELPING ICEsigaction
,忽略有缺陷的库设置的恶意标志)。注意:库本来就不应该设置信号处理程序,而应该允许调用者如果需要的话自行设置。 - R.. GitHub STOP HELPING ICEEINTR
的各个函数的规范(其错误标题下的规范文本)。https://pubs.opengroup.org/onlinepubs/9699919799/functions/V2_chap02.html - R.. GitHub STOP HELPING ICE你的应用程序是否是事件驱动的?(意思是其主循环包括select()/epoll_wait()
调用)。
在事件驱动的应用程序中,你可以阻塞所有信号,并仅在pselect()/epoll_pwait()
调用的持续时间内取消阻塞。这样,你的其余代码就永远不必处理EINTR。
当使用read()函数等待命名管道的输入时,我遇到了类似的问题。
在GNU libc文档中,我找到了有关原语的解释和有用的宏:TEMP_FAILURE_RETRY。
示例:
TEMP_FAILURE_RETRY (read_return = read((int)example_fifo, buffer, (size_t)n));
if (read_return==-1){
fprintf(stderr, "reader.c: read_fifo: read(): %s \n", strerror(errno));
fflush(stderr);
}