Linux 系统调用何时以及如何中断?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/8049756/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
When and how are system calls interrupted?
提问by lxgr
This is a followup question to Is a successful send() "atomic"?, as I think it actually concerns system calls in general, not just sends on sockets.
这是对是否成功发送()“原子”的后续问题?,因为我认为它实际上涉及一般的系统调用,而不仅仅是在套接字上发送。
Which system calls can be interrupted, and when they are, where is the interruption handled? I've learned about SA_RESTART, but don't exactly understand what is going on.
哪些系统调用可以被中断,何时中断,中断在哪里处理?我已经了解了 SA_RESTART,但不完全了解发生了什么。
If I make a system call without SA_RESTART, can the call be interrupted by any kind of interrupts (e.g. user input) that don't concern my application, but require the OS to abort my call and do something else? Or is it only interrupted by signals that directly concern my process (CTRL+C, socket closed, ...)?
When setting SA_RESTART, what are the semantics of a send() or any other "slow" syscall? Will it always block until all of my data is transmitted or the socket goes down, or can it return with a number smaller than the count in send()'s parameter?
Where is restarting implemented? Does the OS know that I want the call to be restarted upon any interrupts, or is some signal sent to my process and then handled by library code? Or do I have to do it myself, e.g. wrap the call in a while loop and retry as often as necessary?
如果我在没有 SA_RESTART 的情况下进行系统调用,该调用是否可以被与我的应用程序无关但要求操作系统中止我的调用并执行其他操作的任何类型的中断(例如用户输入)中断?或者它只是被与我的进程直接相关的信号(CTRL + C,套接字关闭,...)中断?
设置 SA_RESTART 时,send() 或任何其他“慢”系统调用的语义是什么?它会一直阻塞直到我的所有数据都被传输或套接字关闭,还是可以返回一个小于 send() 参数中的计数的数字?
重启在哪里实施?操作系统是否知道我希望在任何中断时重新启动调用,或者是否有一些信号发送到我的进程然后由库代码处理?还是我必须自己做,例如将调用包装在一个 while 循环中并根据需要经常重试?
采纳答案by Hasturkun
System calls can be interrupted by any signal, this includes such signals as SIGINT (generated by CTRL-C), SIGHUP, etc.
系统调用可以被任何信号中断,包括 SIGINT(由 CTRL-C 生成)、SIGHUP 等信号。
When SA_RESTART
is set, a send()
will return (with the sent count) if any data was transmitted before the signal was received, it will return an error EINTR
if a send timeout was set (as those can't be restarted), otherwise the send()
will be restarted.
当SA_RESTART
被设置时,一个send()
将返回(与发送的计数),如果任何数据发送被接收到的信号之前,它会返回一个错误EINTR
,如果一个发送超时被设置(如那些无法重新启动),否则send()
将被重新启动.
System call restarting is implemented in the kernel's signal handling code. The system call internally returns -ERESTARTSYS
upon detecting a pending signal (or having a wait interrupted by a signal), which causes the signal handling code to restore the instruction pointer and relevant registers to the state before the call, making the syscall repeat.
系统调用重启是在内核的信号处理代码中实现的。系统调用-ERESTARTSYS
在检测到未决信号(或等待被信号中断)时在内部返回,这会导致信号处理代码将指令指针和相关寄存器恢复到调用前的状态,从而重复系统调用。