是什么导致发送各种信号?

Nat*_*man 32 process signals

我有时会对进程可以接收的所有信号感到困惑。据我了解,一个进程对这些信号中的每一个都有一个默认处理程序(信号处置),但它可以通过调用sigaction().

所以这是我的问题:是什么导致每个信号被发送?我意识到您可以通过-s参数 to手动向正在运行的进程发送信号kill,但是发送这些信号的自然情况是什么?例如,什么时候SIGINT发送?

另外,对可以处理哪些信号有任何限制吗?甚至SIGSEGV可以处理信号并将控制权返回给应用程序吗?

Gil*_*il' 47

除了进程调用之外kill(2),一些信号是由内核(或有时由进程本身)在各种情况下发送的:

  • 终端驱动程序发送对应于各种事件的信号:
    • 按键通知:( SIGINT请返回主循环)在Ctrl+ 上CSIGQUIT(请立即退出)在Ctrl+ 上\SIGTSTP(请暂停)在Ctrl+ 上Z。可以使用stty命令更改键。
    • SIGTTINSIGTTOU在后台进程尝试读取或写入其控制终端时发送。
    • SIGWINCH 发送信号表示终端窗口的大小已更改。
    • SIGHUP被发送到信号终端已经消失(因为历史上你的modem了^ h UNG,现在通常是因为你已经关闭了终端仿真器窗口)。
  • 某些处理器陷阱可以生成信号。细节取决于架构和系统;以下是典型示例:
    • SIGBUS 对于未对齐的存取存储器;
    • SIGSEGV 用于访问未映射的页面;
    • SIGILL 对于非法指令(错误的操作码);
    • SIGFPE对于带有错误参数的浮点指令(例如sqrt(-1))。
  • 许多信号通知目标进程发生了一些系统事件:
    • SIGALRM通知进程设置的计时器已到期。定时器可以用alarmsetitimer和其他来设置。
    • SIGCHLD 通知进程它的一个子进程已经死亡。
    • SIGPIPE当一个进程在读取端关闭时尝试写入管道时生成(这个想法是,如果您运行foo | barbar退出,则会foo被 a 杀死SIGPIPE)。
    • SIGPOLL(也称为SIGIO)通知进程发生了可轮询事件。POSIX 指定通过I_SETSIG ioctl. 许多系统允许通过O_ASYNC fcntl标志设置的任何文件描述符上的可轮询事件。一个相关的信号是SIGURG,它通知设备(通过 注册I_SETSIG ioctl)或套接字上的紧急数据。
    • 在某些系统上,SIGPWRUPS发出即将发生电源故障的信号时,它会发送到所有进程。

这些列表并不详尽。标准信号在signal.h.

大多数信号可以被应用程序捕获和处理(或忽略)。唯一无法捕获的两个可移植信号是SIGKILL(just die) 和STOP(stop execution)。

SIGSEGV(分段错误) 及其表亲SIGBUS(总线错误) 可以被捕获,但除非您真的知道自己在做什么,否则这是一个坏主意。捕获它们的常见应用是打印堆栈跟踪或其他调试信息。更高级的应用是实现某种进程内内存管理,或者在虚拟机引擎中捕获错误指令。

最后,让我提一下不是信号的东西。当您在从终端读取输入的程序中的一行开头按Ctrl+D时,这会告诉程序已到达输入文件的末尾。这不是信号:它是通过输入/输出 API 传输的。像Ctrl+C和朋友一样,可以用stty.


Jan*_*der 20

首先回答你的第二个问题:SIGSTOP并且SIGKILL不能被应用程序捕获,但其他所有信号都可以,甚至SIGSEGV. 这个属性对于调试很有用——例如,有了正确的库支持,你可以监听SIGSEGV并生成一个堆栈回溯来显示段错误发生的位置。

可以通过man 7 signal从 Linux 命令行键入来获得关于每个信号的作用的官方说法(无论如何对于 Linux)。 http://linux.die.net/man/7/signal有相同的信息,但表格更难阅读。

但是,如果没有一些信号经验,很难从简短的描述中了解它们在实践中的作用,所以这是我的解释:

从键盘触发

  • SIGINT当你击中时发生CTRL+C
  • SIGQUIT由 触发CTRL+\,并转储核心。
  • SIGTSTP当您点击 时暂停您的程序CTRL+Z。与 不同SIGSTOP,它是可捕获的,它使程序vi有机会在挂起自己之前将终端重置为安全状态。

终端交互

  • SIGHUP (“挂断”)是在程序运行时关闭 xterm(或以其他方式断开终端)时发生的情况。
  • SIGTTINSIGTTOU如果程序在后台运行时尝试读取或写入终端,请暂停您的程序。为了SIGTTOU发生,我认为程序需要写入/dev/tty,而不仅仅是默认的标准输出。

由 CPU 异常触发

这意味着您的程序试图做错事。

  • SIGILL表示非法或未知的处理器指令。例如,如果您尝试直接访问处理器 I/O 端口,则可能会发生这种情况。
  • SIGFPE表示存在硬件数学错误;很可能该程序试图除以零。
  • SIGSEGV 意味着您的程序试图访问未映射的内存区域。
  • SIGBUS意味着程序以其他方式错误地访问了内存;我不会详细介绍这个总结。

流程交互

  • SIGPIPE如果您在管道的读取器关闭其末端后尝试写入管道,则会发生这种情况。见man 7 pipe
  • SIGCHLD当您创建的子进程退出或暂停(由SIGSTOP或类似)时发生。

对自发信号有用

  • SIGABRT通常是由程序调用abort()函数引起的,默认情况下会导致核心转储。有点像“紧急按钮”。
  • SIGALRM是由alarm()系统调用引起的,这将导致内核SIGALRM在指定的秒数后将 a传递给程序。见man 2 alarmman 2 sleep
  • SIGUSR1并且SIGUSR2使用程序喜欢。它们对于进程之间的信令很有用。

管理员发送

这些信号通常从命令提示符发送,通过kill命令,fgbgSIGCONT.

  • SIGKILLSIGSTOP是不可阻塞的信号。第一个总是立即终止进程;第二个暂停进程。
  • SIGCONT 恢复暂停的进程。
  • SIGTERM是一个可捕获的版本SIGKILL