由于信号本质上是异步的,因此只要进程在内核模式或用户模式下运行,它就有可能中断进程。
例如,在Robert Love的系统编程中,读取函数已完成,它检查-EINTR并将重新启动系统调用,其余字节将被读取。
ssize_t ret;
while (len != 0 && (ret = read (fd, buf, len)) != 0) {
if (ret == -1) {
if (errno == EINTR)
continue;
perror ("read");
break;
}
len -= ret;
buf += ret;
}
我遇到了来自用户空间的几个ioctl调用,它只是通过检查错误代码<我发现类似的事情也在下面的链接中完成。
IOCTL call and checking return value
对于像ioctl这样的其他系统调用是否需要相同的机制(在读取调用中检查-EINTR)?无论我的程序是否涉及信号处理,始终都需要检查-EINTR的每个系统调用的返回码?
我也听说过Linux支持某些系统调用的自动重启功能,所以如果相应的ioctl调用失败,驱动程序会返回-ERESTARTSYS,但我不确定ioctl系统是否都属于这一类,并且会以透明的方式重新启动所以用户空间donot不得不担心由于信号中断导致的ioctl故障?
如果ioctl部分执行并且信号在中间中断,会发生什么?仍然内核会在没有用户空间介入的情况下自动重启ioctl调用吗?
答案 0 :(得分:1)
Ioctl是设备驱动程序通配符调用(意味着驱动程序可以自由实现其想要的任何功能,无论是否处于休眠状态),因此,如果它决定在某个事件上处于休眠状态,则它也决定是否要休眠被内核中断中断。如果它决定不被中断,则内核仅在进程唤醒后才处理该中断(或将其传递到处于这种状态的另一个线程中)
无论如何,仅在用户模式下将中断传递给用户进程 ,因此内核永远不会挂起系统调用,进入用户模式执行用户信号处理程序,然后返回内核模式结束系统调用。这将破坏系统调用的原子性。如果ioctl调用以不可中断的方式休眠,则该信号将必须等待,并且在 ioctl调用之后发生任何处理程序(或由于中断而导致的系统动作)。
在多线程环境中,如果多个线程中的一个处于这种情况,则具有多个线程的进程可以接收到中断(另一个线程)。内核只是将信号传递到能够处理该信号的可用线程之一。