这是Is a successful send() "atomic"?的后续问题,因为我认为它实际上涉及系统调用,而不仅仅是发送套接字。
哪些系统调用可以被中断,当它们处于什么时候,中断处理在哪里?我已经了解了SA_RESTART,但并不完全了解发生了什么。
如果我在没有SA_RESTART的情况下进行系统调用,可以通过与我的应用程序无关的任何类型的中断(例如用户输入)来中断调用,但要求操作系统中止我的呼叫并执行其他操作?或者它只是被与我的进程直接相关的信号中断(CTRL + C,套接字关闭,......)?
设置SA_RESTART时,send()或任何其他“慢”系统调用的语义是什么?它会一直阻塞,直到我的所有数据都被传输或套接字发生故障,或者它是否能以小于send()参数中的计数的数字返回?
重新启动的位置在哪里?操作系统是否知道我希望在任何中断时重新启动调用,或者是否有一些信号发送到我的进程然后由库代码处理?或者我必须自己做,例如在while循环中包装调用并根据需要重试?
答案 0 :(得分:11)
系统调用可以被任何signal中断,包括SIGINT(由CTRL-C生成),SIGHUP等信号。
设置SA_RESTART
后,如果在收到信号之前传输了任何数据,send()
将返回(带有已发送的计数),如果发送,则会返回错误EINTR
设置了超时(因为无法重启),否则send()
将重新启动。
系统调用重启在内核的信号处理代码中实现。系统调用在检测到挂起信号(或等待信号中断)时在内部返回-ERESTARTSYS
,这导致信号处理代码将指令指针和相关寄存器恢复到调用前的状态,从而使系统调用重复。