好吧,你不是 100% 清楚你对答案的期望,但我会尽量涵盖一般的想法。
首先,您可以称之为“调试”信号的是(以及何时期望它们):
SIGILL
, SIGFPE
— 如果程序试图运行非法指令,通常会出现错误CFLAGS
和/或自己的程序集(或严重的随机损坏);
SIGABRT
— 由abort()
呼叫引起,例如在assert()
. 它也可以来自库,因此您通常应该处理它;
SIGSEGV
——无效的内存访问,你可能已经知道了;
SIGBUS
— 在使用 I/Ommap()
并尝试读/写不可访问的内存时可能发生;当mmap()
基于 - 的 I/O 空间不足时,我也遇到过这种情况;
SIGPIPE
— 在管道上进行 I/O 时,管道与另一端断开连接;
- POSIX 还指定
SIGSYS
了无效的系统调用,您可能也想抓住它(尽管我从未设法看到一个)。
如果您使用相关操作,我会说您需要处理这些信号。它们都在 POSIX 中,但我不确定是否所有系统都实现了它们,所以#ifdef
无论如何你可能都想为它们使用 s (SIG*
保证是宏,因此适用于#ifdef
)。
您在程序运行时可能遇到的其他信号是:
SIGALRM
— 使用时alarm()
,
SIGPOLL
— 使用轮询时,
SIGCHLD
— 当产生进程时……</li>
这些基本上是您在使用相关操作时正在处理的信号,尽管它们默认终止,但无论如何您都应该为它们提供其他处理程序。
最后,如果您希望处理user发送的信号,这是一个苛刻的情况——因为 user 实际上可以发送每个信号。因此,如果您想优雅地处理这一切,您需要捕获man signal
默认为终止或中止操作的每个信号。
如果您只想捕获您可以预期的常见信号子集,这些将是:
SIGHUP
当带有程序的终端(或其他相关的父级)死亡时,
SIGINT
对于 ^c 键,
SIGQUIT
对于 ^\ 键,
SIGTERM
对于终止请求(kill
默认由程序和其他类似工具发送),
SIGUSR1
和SIGUSR2
是用户定义的信号,通常用于执行程序特定的操作。它们是由用户发送的,并且——出于某种原因——默认杀死程序。
也有SIGKILL
,但标准不允许捕捉它。
我希望我涵盖了最重要的信号。请注意,我是 Linux 用户,其他 *nixes 可能有一些您也可能想要捕捉的特定信号。
这通常完全取决于您想要实现的目标。虽然防止软件被随机信号打断是个好主意,但通常不值得阻止它被所有这些信号杀死,尤其是那些仅由用户直接发送的信号。
如果用户想要杀死应用程序,无论如何他都可以实现它,并且只需处理常见的应用程序就足够了 -SIGINT
和SIGTERM
. 我个人希望SIGQUIT
(^\ key) 杀死应用程序而不让它完成甚至关键的任务(就像这样SIGKILL
做)。
编辑. 作为最后一句话的理由,请考虑以下几点:我刚刚做了一些愚蠢的事情,比如删除了一些重要数据。或者只是注意到退出时清理程序有问题。我真的很想终止程序,确保我的信号不会被捕获,但会立即返回。即使它会导致数据损坏,有时我真的更喜欢有损坏的数据(希望我能够恢复我需要的东西)而不是没有数据。