我是系统编程的新手,我遇到了这个程序。
#include "apue.h"
static void sig_alrm(int);
int main(void)
{
int n;
char line[MAXLINE];
if (signal(SIGALRM, sig_alrm) == SIG_ERR)
err_sys("signal(SIGALRM) error");
alarm(10);
if ((n = read(STDIN_FILENO, line, MAXLINE)) < 0)
err_sys("read error");
alarm(0);
write(STDOUT_FILENO, line, n);
exit(0);
}
static void sig_alrm(int signo)
{
/* nothing to do, just return to interrupt the read */
}
此程序旨在为read()系统调用提供超时。如果read()需要超过30秒,那么将生成一个信号。现在,
从教科书中引用(它列出了程序中的2个缺陷,其中之一是)
如果系统调用自动重启,则SIGALRM不会中断读取 信号处理程序返回在这种情况下,超时不执行任何操作。
我无法理解这句话的意思。有人可以解释一下吗
感谢。
答案 0 :(得分:2)
以下注意事项对Linux&lt; = 2.6.11有效,但我相信这些概念也适用于最近的内核。
如果某个进程在系统调用中被阻止,则会将其置于TASK_INTERRUPTIBLE
或TASK_UNINTERRUPTIBLE
状态的等待队列中。在前一种情况下,在接收到信号后,内核将其重新置于TASK_RUNNING
状态,将进程添加到runqueue并将信号添加到挂起信号列表中。
安排进程后,它会继续执行系统调用。由于系统调用未完成,可能的返回码为:
EINTR
ERESTARTNOHAND
ERESTART_RESTARTBLOCK
ERESTARTSYS
ERESTARTNOINTR
在系统调用的退出路径上,检查挂起的信号。在这种情况下,调用您的SIG_ALRM
处理程序,然后内核立即检查系统调用的返回代码。通常,可能会发生以下情况:
EINTR
:用户模式进程已恢复,read
的返回值将完全符合-EINTR ERESTARTNOINTR
:系统调用已重新执行ERESTARTSYS
:如果设置了SA_RESTART标志,则重新执行系统调用,否则将-EINTR返回给用户空间。ERESTARTNOHAND
或ERESTART_RESTARTBLOCK
:恢复用户模式进程并返回-EINTR。重新执行系统调用意味着进程EIP减少2,因此强制它再次执行int 0x80
。
在这种特定情况下,如果进程在STDIN的读取系统调用上被阻止,并且从SIG_ALRM
收到man 7 signal
,则信号处理程序中断系统调用和库函数< /强>:
If a blocked call to one of the following interfaces is
interrupted by a signal handler, then the call will be
automatically restarted after the signal handler returns
if the SA_RESTART flag was used; otherwise the call will
fail with the error EINTR.
* read(2), readv(2), write(2), writev(2), and ioctl(2)
calls on "slow" devices. A "slow" device is one where the
I/O call may block for an indefinite time, for example, a
terminal, pipe, or socket. (A disk is not a slow device
according to this definition.) If an I/O call on a slow
device has already transferred some data by the time
it is interrupted by a signal handler, then the call
will return a success status (normally, the number of bytes
transferred).
这是ERESTARTSYS返回代码的行为,即只有在设置SA_RESTART时捕获信号时才重新执行系统调用,否则 它将返回EINTR(如果尚未传输数据)。
所以你书中的第一句话
If system calls are automatically restarted [...]
表示
If, upon receiving a signal, SA_RESTART is set
如果是,系统调用重新启动,它将再次阻止,警报不会产生任何影响。
<强>参考文献:强>