当进程正在执行一个低速系统调用且处于阻塞期间时,如果进程捕获到一个信号,则该调用被中断,不再继续执行。 该系统调用返回出错,起errono设置为EINTR。 因为发生信号, 进程捕捉到它, 这将是一个很好的机会来唤醒阻塞的系统调用。
与被中断的系统调用相关的问题是必须显示的处理这种出错返回,判断出错是否是因为被信号中断导致,看系统是否支持自动重启,以及我们是否需要重启被信号中断的系统调用。
如果系统不自动重启这些被中断的系统调用,而我们希望重启,通常有2种方法,一是通过出错后检查errno,这是比较通用的方法,如下:
again:
if((n=read(fd,buf,BUFFSEZE))<0)
{
if(errno==EINTR) //改错误是因为被信号中断
goto again;
}
|
另一种方法是在sigaction中设置允许重新启动被特定信号中断的系统调用的标志SA_RESTART(有些系统可能不支持):act.sa_flags |= SA_RESTART;
某些系统引入了某些被中断后自动重启动的系统调用,如ioctl,read,readv,write,writev...,但这也会带来一些问题,如果我们并不希望重启这些被中断的调用,这时可以通过sigaction禁止重启,act.sa_flags |= SA_INTERRUPT。
上述只是针对可能被阻塞的低速的系统调用,如果系统调用执行时没有阻塞,则其不会被信号中断,即使这时发生了信号。如果是设置了非阻塞的系统调用,则不必考虑被信号中断的问题了。
阅读(1300) | 评论(0) | 转发(0) |