#include <signal.h>
int sigemptyset(sigset_t *set); // 初始化信号集 set 为 empty,不包含任何信号
int sigfillset(sigset_t *set); // 初始化信号集 set 为 full,包含所有信号
int sigaddset(sigset_t *set, int signum); // 向信号集 set 中添加 signum 信号
int sigdelset(sigset_t *set, int signum); // 从信号集中 set 中删除 signum 信号
int sigismember(const sigset_t *set, int signum); // 判断信号集 set 中是否包含 signum 信号
int raise(int sig); // 向当前进程发送信号 sig
int kill(pid_t pid, int sig); // 向进程号为 pid 的进程,发送 sig 信号
信号相关接口
#include <signal.h>
int raise(int sig); // 向当前进程发送信号 sig
int kill(pid_t pid, int sig); // 向进程号为 pid 的进程,发送 sig 信号
int sigwait(const sigset_t *set, int *sig); // 挂起正在执行的线程直到收到 set 中的信号之一,函数接收到信号之后会将信号置于 sig 中返回
typedef void(*sighandler_t)(int);
sighandler_t signal(int signum, sighandler_t handler); // 检查或修改与 signum 信号相关联的处理动作,在不同的 unix 下的行为不同,避免使用,应该使用 sigaction 代替
int sigaction(int signum, const struct sigaction *act, struct sigaction *oldact); // 检查或修改与 signum 信号相关联的处理动作,在设置新的处理函数act的同时也保留原有的信号处理函数
关于struct sigaction中的sa_mask成员
sigset_t sa_mask 是进程的信号屏蔽字,在调用信号捕捉函数之前,将需要阻塞的信号加入这个sa_mask,仅当信号捕捉函数正在执行时才会阻塞 sa_mask 中的信号,当信号捕捉函数返回时,进程的信号屏蔽字会复位,复位动作由sigaction函数处理,不用自己处理。
示例如下:
#include <stdio.h>
#include <signal.h>
#include <unistd.h>
#include <sys/types.h>
void signal_handler(int signal, siginfo_t* info, void* null)
{
printf("trap signal : %d
", signal);
while(1); // 一直处于调用态,无法返回
}
int main()
{
struct sigaction act;
act.sa_sigaction = signal_handler;
sigemptyset(&act.sa_mask);
sigaddset(&act.sa_mask, SIGINT); // 设置调用 signal_handler 时,阻塞 SIGINT 信号
act.sa_flags = 0;
sigaction(SIGSEGV, &act, NULL);
raise(SIGSEGV); // 向本进程发送 SIGSEGV 信号,触发处理函数 signal_handler 的调用
return 0;
}
// 以上程序运行起来时, Ctrl + C (SIGINT) 将无法停止程序
// 原因在于 signal_handler 一直在运行且无法返回,sa_mask又设置了对 SIGINT 的运行时阻塞