Linux: 系统调用有自己的信号处理程序吗?我可以覆盖它吗?

Linux: does a system call have its own signal handler? Can I override it?

关于系统调用 read() 的文档说 read() 如果被信号中断则立即 returns。返回值反映了到目前为止它成功读取了多少字节。这似乎暗示某些系统调用有自己的信号处理程序。

如果 read() 正在从管道读取(由 pipe() 设置),但管道中没有可用字节,因此 read() 正在阻塞线程。现在,如果我从终端发送 SIGINT(通过 Ctrl+C),程序将终止。

假设在程序启动时我为 SIGINT 安装了一个信号处理程序,它打印一条消息 "SIGINT is received"。当 read() 阻塞并且我使用 Ctrl+C 时,程序会终止并打印该消息,还是程序仍会静默终止,因为 SIGINT 已由 read() 的信号处理程序处理?

(我的实验表明是后一种情况..不确定)

It seems to imply some system calls have their own signal handlers.

不,绝对不是。根据 read(2) 手册页,当读取被信号中断时 returns EINTR。要实现此行为,您必须处理信号,即为其安装处理程序。如果您发送信号而不处理它,那么程序将终止。

现在假设您已经处理了 SIGINT 信号并在程序在 read(2) 上被阻塞时发送了它,那么根据您安装信号处理程序的方式可以观察到两种行为。

  1. 如果使用 sigaction(2) and SA_RESTART is used then according to signal(7) 手册页处理信号,处理程序将在信号处理程序 returns.
  2. 后执行并自动重新启动读取
  3. 如果未使用 SA_RESTART 标志,则调用失败并显示错误 EINTR。

在这两种情况下,程序都不会终止,因为已处理 SIGINT。

Suppose at the program's start I installed a signal handler for SIGINT that prints a message "SIGINT is received". When read() is blocking and I use Ctrl+C, will the program terminate with that message printed, or will the program still terminate silently because SIGINT is already handled by read()'s signal handler?

在这两种情况下程序都不会终止。将打印处理程序消息 "SIGINT is received",程序将继续执行。