介绍
#include <signal.h>
int sigaction(int signum, const struct sigaction *act,
struct sigaction *oldact);
功能:为一个信号设置处理函数
参数:
-
signum:要捕获的信号类型
-
act:新的信号处理方式
struct sigaction { void (*sa_handler)(int); // 指定信号处理函数 void (*sa_sigaction)(int, siginfo_t *, void *); sigset_t sa_mask; // 临时在进程原有信号掩码的基础上增加信号掩码,指定哪些信号不能发送给本进程,当前处理函数执行完毕,临时屏蔽自动解除 /* sigset_t 和 fd_set 类似,通过以下函数来设置、修改、删除和查询信号集 #include <signal.h> int sigemptyset(sigset_t *set); int sigfillset(sigset_t *set); int sigaddset(sigset_t *set, int signum); int sigdelset(sigset_t *set, int signum); int sigismember(const sigset_t *set, int signum); */ int sa_flags; // 设置程序收到信号时的行为 void (*sa_restorer)(void); // 已经过时,最好不使用 };
-
oldact:信号先前的处理方式
返回值:
- 成功返回 0
- 失败返回 -1,并设置 errno
简单使用
void addsig(int sig, void handler(int), bool restart = true)
{
strcut sigaction sa;
memset(sa, '\0', sizeof(sa));
sa.sa_handler = handler;
if (restart) {
/* 如果程序在执行处于阻塞状态的系统调用时接收到信号,
并且我们为该信号设置了信号处理函数,则默认情况下系统调用将被中断,
并且 errno 被设置为 EINTR。可以使用 sigaction 函数
为信号设置 SA_RESTART 标志以自动重启被信号中断的系统调用。
*/
sa.sa_flag |= SA_RESTART;
}
sigfillset(&sa.sa_mask);
int ret = sigaction(sig, &sa, nullptr);
assert(ret != -1);
(void)ret;
}
注意事项
- 除了用户自定义信号处理函数外,bits/signum.h 头文件中还定义了信号的两种其他处理方式。
#include <bits/signum.h>
#define SIG_DFL ((__sighandler_t) 0) // 表示使用信号的默认处理方式
#define SIG_IGN ((__sighandler_t) 1) // 表示忽略目标信号
- 默认情况下,往一个读端关闭的管道或 socket 连接中写数据将引发 SIGPIPE 信号。我们需要在代码中捕获并处理该信号,或者至少忽略它,因为程序接收到该信号的默认行为是结束进程,而我们不希望因为错误的写操作导致程序退出。