捕获信号时系统调用的中断

捕获信号时系统调用的中断

通过阅读“read()”和“write()”调用的手册页,似乎这些调用会被信号中断,无论它们是否必须阻塞。

具体来说,假设

  • 一个进程为某些信号建立处理程序。
  • 打开一个设备(比如终端...),但未设置“O_NONBLOCK”(即以阻塞模式运行)
  • 然后,该进程进行“read()”系统调用来从设备读取,并最终在内核空间中执行内核控制路径。
  • 当进程在内核空间执行其“read()”时,先前安装了处理程序的信号将被传送到该进程,并调用其信号处理程序。

阅读手册页和 SUSv3‘系统接口卷(XSH)’中的相应部分可以发现:

i. 如果 read() 在读取任何数据之前被信号中断(即由于没有可用数据而必须阻塞),它将返回 -1,并将 'errno' 设置为 [EINTR]。

ii. 如果 read() 在成功读取一些数据后被信号中断(即可以立即开始处理请求),它将返回读取的字节数

问题A):

我是否可以正确地假设,在任何一种情况下(阻塞/无阻塞),信号的传递和处理对于“read()”来说并不完全透明?

情况 i. 似乎是可以理解的,因为阻塞“read()”通常会将进程置于“TASK_INTERRUPTIBLE”状态,这样当发出信号时,内核会将进程置于“TASK_RUNNING”状态。

但是,当“read()”不需要阻塞(情况 ii.)并在内核空间中处理请求时,我会认为信号的到达及其处理将是透明的,就像硬件中断的到达和正确处理一样。特别是,我会假设在传递信号后,该过程将被暂时置于用户模式以执行其信号处理程序,最终它将返回以完成对中断的“read()”(在内核空间中)的处理,以便“read()”运行完毕,之后该过程返回到调用“read()”之后的点(在用户空间中),结果读取所有可用字节。

但是 ii。似乎意味着“read()”被中断,因为数据立即可用,但它返回的是“部分”数据(而不是全部)。

这让我想到了第二个(也是最后一个)问题

问题B):

如果我在 A) 下的假设是正确的,那么为什么 'read()' 会被中断,即使它不需要阻塞,因为有可用的数据可以立即满足请求?换句话说,为什么在执行信号处理程序后没有恢复 'read()',最终导致返回所有可用数据(毕竟是可用的)?

答案1

关于这一点,有一个有趣的讨论Unix 哲学页。基本上,它简化了内核设计。我相信 *BSD 有自动重新启动中断的系统调用的选项。但在 Linux 上,您必须编写一个包装函数来处理它。

相关内容