信号处理和中断处理问题

7
在进程执行阻塞系统调用时(例如读或写),有一个信号到达。此时,该系统调用是否会以EINTR的错误码终止?在处理完信号后,系统调用是否会重新启动?
假设系统调用以EINTR错误码终止,在返回用户空间之前,内核会处理信号。
信号处理程序是在用户模式还是内核模式下执行的?如果是在用户模式下执行,那么在处理完信号后,会返回到系统调用(read/write)期间的指令吗?还是再次进入内核模式处理信号,并从ret_from_syscall返回给用户?在系统调用期间出现信号后,执行如何恢复到该系统调用之后的指令?
通过在sigaction中传递SA_RESTART标志,是否可以重新启动系统?
1个回答

3

信号在用户模式下执行,但使用不同的用户上下文,然后返回内核,再通过ret_from_syscall返回到用户模式。当使用SA_RESTART安装信号处理程序时,系统调用的行为取决于系统调用。

关于哪些系统调用会被重新启动的说明可在最近版本的信号概述手册页中找到:

man 7 signal

如果不使用 SA_RESTART 标志,则系统调用不会重新启动。

1
现在我明白了你所说的信号是在不同用户上下文中执行的意思。如果进程接收到一个信号,进程会切换到内核模式来处理异常,在当前进程的信号数组位掩码中设置。在返回用户模式之前,内核会检查信号挂起并调用do_signal函数来处理信号,该函数又调用handle_signal函数来复制内核硬件上下文,并通过调用setup_frame修改用户模式堆栈。 - Ganesh Kundapur
新的堆栈帧包含signum、指向用户模式信号处理程序的PC值,以及包含系统调用sigreturn地址的返回地址字段。进程返回到用户模式时,它开始执行信号处理程序,并在终止时执行sigreturn,使进程切换到内核模式,在那里通过restore_sigcontext将硬件上下文从用户模式堆栈复制回内核堆栈(将用户模式堆栈恢复到原始状态)。当sigreturn系统调用终止进程时,进程会切换回用户模式并从信号之前离开的地方继续执行。 - Ganesh Kundapur
重要的是要注意,SA_RESTART并不总是适用。一些接口在被信号处理程序中断后永远不会重新启动,无论是否使用了SA_RESTART;它们在被信号处理程序中断时总是失败并显示EINTR错误。请查看信号手册获取详细信息。 - kikeenrique

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接