我正在为嵌入式 Linux 系统编写用户应用程序,并且正在为设备使用常用功能,例如打开、关闭、读取、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。
您的应用程序事件驱动吗?(意味着它的主循环包括select()/epoll_wait()
调用)。
在事件驱动的应用程序中,您可以阻止所有信号,并且仅在pselect()/epoll_pwait()
调用期间解除阻止它们。这样,您的其余代码就不必处理 EINTR。
我知道这个问题很老,但我认为还有更多要说的。回答标题中的具体问题:基本上,从不。
除了select
and之外poll
,EINTR
只有在您安装了中断信号处理程序时才会发生(错误/不了解如何使用sigaction
,或者因为您希望能够中断阻塞操作)。当函数失败时循环重试EINTR
只是撤消它。这样做是 80 年代和 90 年代初到中期的一种旧的反模式,当时许多操作系统都存在错误,并且据报道是EINTR
在不符合要求的情况下生成的,但这些错误早已不复存在。
有可能,即使在您希望能够用信号中断事物的应用程序中,有些代码的成功完成非常重要,以至于您不能将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);
}