5

最近我正在开发一个用 c 编写的软件,它有大约 3-4 千行代码。当我开始遇到分段错误时,我添加了一个 SIGSEGV 处理程序。这有助于我在处理程序被制作时指出错误给一个回溯。

我的问题是除了 SIGSEGV 之外,当我们拥有大型软件时,应该处理哪些重要信号,这样错误检测就会很容易。

这可以选择用于防止攻击。Ex 软件在进行关键更新/操作时接收中止信号。标准告诉 SIGHUP、SIGINT、SIGKILL、SIGPIPE、SIGTERM 和其他一些信号具有终止该信号传递到的进程的默认属性。

因此,要为我的软件添加另一层保护,我将不得不改变这些信号的行为。通过保护,我的意思是我不希望我的软件在关键更新之间终止,我将决定何时终止中止。

编辑:我想知道软件设计得如何,如何处理信号,像安全网一样使用它们,这有助于软件的构建。

4

1 回答 1

8

好吧,你不是 100% 清楚你对答案的期望,但我会尽量涵盖一般的想法。

首先,您可以称之为“调试”信号的是(以及何时期望它们):

  1. SIGILL, SIGFPE— 如果程序试图运行非法指令,通常会出现错误CFLAGS和/或自己的程序集(或严重的随机损坏);
  2. SIGABRT— 由abort()呼叫引起,例如在assert(). 它也可以来自库,因此您通常应该处理它;
  3. SIGSEGV——无效的内存访问,你可能已经知道了;
  4. SIGBUS— 在使用 I/Ommap()并尝试读/写不可访问的内存时可能发生;当mmap()基于 - 的 I/O 空间不足时,我也遇到过这种情况;
  5. SIGPIPE— 在管道上进行 I/O 时,管道与另一端断开连接;
  6. POSIX 还指定SIGSYS了无效的系统调用,您可能也想抓住它(尽管我从未设法看到一个)。

如果您使用相关操作,我会说您需要处理这些信号。它们都在 POSIX 中,但我不确定是否所有系统都实现了它们,所以#ifdef无论如何你可能都想为它们使用 s (SIG*保证是宏,因此适用于#ifdef)。

您在程序运行时可能遇到的其他信号是:

  1. SIGALRM— 使用时alarm()
  2. SIGPOLL— 使用轮询时,
  3. SIGCHLD— 当产生进程时……</li>

这些基本上是您在使用相关操作时正在处理的信号,尽管它们默认终止,但无论如何您都应该为它们提供其他处理程序。

最后,如果您希望处理user发送的信号,这是一个苛刻的情况——因为 user 实际上可以发送每个信号。因此,如果您想优雅地处理这一切,您需要捕获man signal默认为终止或中止操作的每个信号。

如果您只想捕获您可以预期的常见信号子集,这些将是:

  1. SIGHUP当带有程序的终端(或其他相关的父级)死亡时,
  2. SIGINT对于 ^c 键,
  3. SIGQUIT对于 ^\ 键,
  4. SIGTERM对于终止请求(kill默认由程序和其他类似工具发送),
  5. SIGUSR1SIGUSR2是用户定义的信号,通常用于执行程序特定的操作。它们是由用户发送的,并且——出于某种原因——默认杀死程序。

也有SIGKILL,但标准不允许捕捉它。

我希望我涵盖了最重要的信号。请注意,我是 Linux 用户,其他 *nixes 可能有一些您也可能想要捕捉的特定信号。

这通常完全取决于您想要实现的目标。虽然防止软件被随机信号打断是个好主意,但通常不值得阻止它被所有这些信号杀死,尤其是那些仅由用户​​直接发送的信号。

如果用户想要杀死应用程序,无论如何他都可以实现它,并且只需处理常见的应用程序就足够了 -SIGINTSIGTERM. 我个人希望SIGQUIT(^\ key) 杀死应用程序而不让它完成甚至关键的任务(就像这样SIGKILL做)。

编辑. 作为最后一句话的理由,请考虑以下几点:我刚刚做了一些愚蠢的事情,比如删除了一些重要数据。或者只是注意到退出时清理程序有问题。我真的很想终止程序,确保我的信号不会被捕获,但会立即返回。即使它会导致数据损坏,有时我真的更喜欢有损坏的数据(希望我能够恢复我需要的东西)而不是没有数据

于 2012-07-23T20:39:43.153 回答