通过阅读read()
和write()
调用上的手册页,可以看出这些调用被信号打断了,而不管它们是否必须阻塞。
特别地,假设
- 进程为某些信号建立处理程序。
O_NONBLOCK
未设置(即以阻止模式运行)打开设备(例如,终端)- 然后,该过程将进行
read()
系统调用以从设备读取数据,从而执行内核空间中的内核控制路径。 - 当程序
read()
在内核空间中执行时,先前安装了处理程序的信号将传递到该进程,并调用其信号处理程序。
阅读SUSv3“系统接口卷(XSH)”中的手册页和相应部分,您会发现:
一世。如果a read()
在读取任何数据之前被信号打断(即由于没有可用数据而不得不阻塞),则它将返回-1并将其errno
设置为[EINTR]。
ii。如果a read()
在成功读取某些数据后被信号中断(即可以立即开始处理请求),则它将返回读取的字节数。
问题A):
我是否正确地假设在任何一种情况下(块/无块)信号的传递和处理对信号都不完全透明read()
?
案例一 这似乎是可以理解的,因为阻塞read()
通常会将进程置于TASK_INTERRUPTIBLE
状态,以便在传递信号时,内核会将进程置于TASK_RUNNING
状态。
但是,当read()
不需要阻塞(情况ii。)并在内核空间中处理请求时,我会认为信号的到达及其处理将是透明的,就像硬件的到达和正确处理一样中断会。特别是,我会假设在传递信号后,该过程将被暂时置于用户模式下以执行其信号处理程序,然后该信号处理程序将最终返回该用户处理程序,以完成对中断read()
(在内核空间中)的处理,从而read()
运行其直到完成为止,然后过程返回到调用read()
(在用户空间中)之后的点,结果将读取所有可用字节。
但是ii。似乎暗示read()
中断了,因为数据立即可用,但是它返回时仅返回部分数据(而不是全部)。
这使我想到了第二个(也是最后一个)问题:
问题B):
如果我在A)下的假设是正确的,那么read()
即使不需要阻塞,因为有可用的数据可以立即满足请求,为什么会被中断?换句话说,为什么read()
在执行信号处理程序后不能恢复,最终导致所有可用数据(毕竟是可用的)被返回?