最近我正在开发一个用c编写的软件,该软件大约有3-4千行代码。当我开始发现分段错误时,我添加了一个SIGSEGV处理程序。这有助于我在处理程序进行回溯时确定错误。
我的问题是,除了SIGSEGV之外,当我们有一个大型软件时,应该处理哪些重要信号,这样错误检测就会很容易。
这可以选择性地用于防止攻击。Ex软件在进行关键更新/操作时接收中止信号。标准告诉SIGHUP、SIGINT、SIGKILL、SIGPIPE、SIGTERM和其他一些信号具有默认属性,可以终止将该信号传递到的进程。
因此,为了给我的软件添加另一层保护,我必须改变这些信号的行为。所谓保护,我的意思是我不希望我的软件在关键更新之间终止,我会决定何时中止。
编辑:我想知道软件设计得有多好,处理SIGNAL,像使用安全网一样使用它们,这有助于软件的构建。
好吧,你还不能100%清楚你对答案的期望,但我会试着介绍一下大致的想法。
首先,你可以称之为"调试"信号的是(以及何时预期):
SIGILL
、SIGFPE
——如果程序试图运行非法指令,通常会出现错误的CFLAGS
和/或自己的程序集(或严重的随机损坏)SIGABRT
-由abort()
调用引起,例如在assert()
中。它也可以来自库,所以你通常应该处理它SIGSEGV
——无效内存访问,您可能已经知道它的全部内容SIGBUS
——当使用mmap()
进行I/O并尝试读取/写入不可访问的内存时可能发生;当基于mmap()
的I/O空间不足时,我也遇到过这种情况SIGPIPE
——对管道进行I/O时,管道与另一侧断开- POSIX还为无效的系统调用指定了
SIGSYS
,您可能也想捕获它(尽管我从未看到过)
我想说,如果你正在使用相关的操作,你需要处理这些信号。它们都在POSIX中,但我不确定是否所有系统都实现了它们,所以你可能无论如何都想为它们使用#ifdef
(SIG*
保证是宏,因此适合#ifdef
)。
您可能在程序运行时遇到的其他信号包括:
- CCD_ 16-当使用CCD_
- CCD_ 18-当使用轮询时
SIGCHLD
——当产卵过程
这些基本上是在使用相关操作时无论如何都要处理的信号,尽管它们在默认情况下终止,但无论如何都应该有其他处理程序。
最后,如果您希望处理用户发送的信号,这是一个苛刻的情况——因为用户实际上可以发送每个信号。因此,如果您想优雅地处理这一切,您需要捕获来自man signal
的每个信号,该信号默认为终止或中止操作。
如果你只想捕捉一个你可以预期的常见信号子集,这些信号将是:
- CCD_ 21,当具有程序的终端(或者如果相关的话
- 针对^c密钥的CCD_ 22
- ^\key的CCD_ 23
- 用于终止请求的CCD_ 24(默认由CCD_
- CCD_ 26和CCD_。它们是由用户发送的,并且由于某种原因,默认为终止程序
还有SIGKILL
,但标准不允许捕捉
我希望我涵盖了最重要的信号。请注意,我是一名Linux用户,其他*nixe可能也有一些特定的信号,您可能也想捕捉。
这通常都取决于你想要实现什么。虽然防止软件被随机信号打断是个好主意,但通常不值得防止它被所有信号杀死,尤其是那些只由用户直接发送的信号。
如果用户想杀死应用程序,他无论如何都可以实现,并且应该足以处理常见的应用程序——SIGINT
和SIGTERM
。我个人希望SIGQUIT
(^\key)在不让应用程序完成关键任务的情况下终止应用程序(就像SIGKILL
一样)。
编辑。最后一句话的基本原理是:我只是做了一些愚蠢的事情,比如删除了一些重要的数据。或者只是注意到退出过程中的清理有问题。我真的想终止程序,确保我的信号不会被捕获,但会立即返回。即使这会导致数据损坏,有时我真的更喜欢有损坏的数据(希望我能够恢复我需要的东西),而不是没有数据。