我正在为嵌入式Linux系统编写用户应用程序,我正在使用常用功能,如open,close,read,ioctl等设备。现在,我读到了有关EINTR的信息,表明该功能被信号中断,但我不确定其含义。在我所有的示例程序中,有时它已完成,例如ioctl(),有时它没有完成,例如读()。所以,我有点困惑。
我什么时候最好检查EINTR并重复功能调用?
答案 0 :(得分:14)
请参阅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。
答案 1 :(得分:4)
你的应用程序事件是否被驱动? (意思是它的主循环包括select()/epoll_wait()
调用)。
在事件驱动的应用程序中,您可以阻止所有信号,并仅在pselect()/epoll_pwait()
呼叫期间取消阻止它们。这样,您的其余代码就不必处理EINTR。
答案 2 :(得分:3)
答案 3 :(得分:3)
我知道这个问题很老,但我认为还有很多话要说。要回答标题中的特定问题:基本上,从不。
除了select
和poll
之外,EINTR
只能在安装后发生(由于错误/不了解如何使用sigaction
,或者由于您< strong>想要以能够中断阻止操作)中断信号处理程序。当函数EINTR
失败时循环重试只会取消该操作。这样做是从80年代到90年代初到90年代中期的一种古老的反模式,当时许多操作系统存在bug,据说在不合格的情况下会生成EINTR
,但这些bug早已消失。
即使在您希望能够用信号中断事物的应用程序中,也有一些代码的成功完成是如此重要,以至于您不能将EINTR
视为错误条件,并且不完成操作就返回给呼叫者。在这种情况下,安装一个重试循环可能是有意义的,但最好在操作过程中屏蔽信号(至少是可能中断的信号),并在完成后取消屏蔽。
答案 4 :(得分:1)
在等待来自带有read()的命名管道的输入时,我遇到了类似的问题。
我在GNU libc documentation中找到了原语的解释和有用的宏: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);
}