信号是发送给一个进程或进程组的短消息,内核使用信号通知进程系统时间的发生,信号也用于进程间的通信。Linux把信号分类成两组,即通用POSIX(经典UNIX信号)和实时信号,每组由32个不同信号构成,由一个唯一ID标识。
#define SIGHUP 1
#define SIGINT 2
等等
通用类信号组里的信号被绑定到特定系统时间并由于合适的宏定义命名,那些实时分类中的信号并不绑定特定事件,由应用程序自由用于进程间通信,内核给他们起了一般名字:SIGRTMIN 和 SIGRTMAX
信号产生那一刻,内核传递信号事件给目标进程,而进程可以依照配置的相应行为(action)响应信号,即信号处置。
下面是可由进程设置为处置的操作(action)列表,进程可以在任意时间点设置一个操作(action)为其信号处置,但是可以任意次、无限制的在这些行为之间切换。
Kernel handler:内核为每个信号实现的默认处理函数,进程可以通过它任务结构体的信号处理表获得这些处理函数。在接收到信号之后,进程可以请求执行合适的信号处理程序,这是默认配置
Process defined handler: 进程被允许实现它自己的信号处理函数,并设置它们为响应信号事件时被执行,这一切通过恰当的系统调用接口成为可能,接口允许进程绑定自己的处理函数到信号。信号一发生,进程处理函数就被异步的调用。
Ignore:进程亦被允许忽略信号的发生,但是它需要通过调用适当的系统调用来生命忽略的意图。
内核定义的默认处理程序能执行下列任何操作(action):
Ignore : 啥都不发生
Terminate : 杀死进程,
Coredump: 写一个core dump 文件描述所有线程并杀死所有线程
Stop : 停止组的所有线程
信号管理API
应用程序被提供各种api以管理信号;我们挑选重要的来看:
sigaction():用户模式进程使用它检查或者更改信号的action设置。此API提供大量属性标识来更进一步定义信号的行为:
#include <signal.h>
int sigaction(int signum , const struct sigaction* act , struct sigaction* oldact);
sigaction 结构体被定义如下:
struct sigaction{
void (* sa_handler)(int);
void (* sa_sigaction)(int,siginfo_t *, void *);
sigset_t sa_mask;
int sa_flags;
void (* sa_restorer)(void);
}
int signum 是信号的数字ID。sigaction()测试或设置操作(action)跟这个信号关联。
const struct sigaction * act 被赋值一个struct sigaction 实例地址。结构体里指定的操作(action)变成了绑定到信号的新操作(action),当指针为null,当前信号的操作不变。
struct sigaction* oldact 是个输出参数,需要由一个未初始化struct sigaction实例的地址来初始化。函数通过这个参数返回此信号当前关联的操作(action)。