信号检测是项目开发中必不可少的!提到信号处理机制,很多人都会想到signal函数吧
void handle_signal(int signal) {
printf("接收到信号: %d\n", signal);
if(SIGINT == signo)
{}
else if(SIGTERM == signo)
{}
// 退出程序
exit(signal);
}
int main() {
// 注册信号处理函数
signal(SIGINT, handle_signal); // 当接收到中断信号(SIGINT)时调用handle_signal函数
}
除了这种方式,还有一种操作信号集的方式更为精确,能够屏蔽,添加,删除,操作等某个信号。这些函数仅支持对 POSIX 信号集进行操作。首先了解下这几个函数:
int sigemptyset(sigset_t *set)
描述:
清空信号集set
参数:
set:用来存储信号集的值
返回值:
成功:0;失败:-1
int sigfillset(sigset_t *set)
描述:
将信号集set填满;就是把所有的信号都放在这个集合里;但是不会包含 NPTL 线程实现内部使用的两个实时信号:SIGCANCEL和SIGSETXID
参数:
set:用来存储信号集的值
返回值:
成功:0;失败:-1
int sigaddset(sigset_t *set, int signum)
描述:
将某个信号signum添加到信号集set
参数:
set:信号集
signum:某种信号
返回值:
成功:0,失败:-1
int sigdelset(sigset_t *set, int signum)
描述:
将某个信号signum从信号集中删除
参数:
set:信号集
signum:某个信号
返回值:
成功:0;失败:-1
int sigismember(const sigset_t *set, int signum)
描述:
检查某个信号signum是否在信号集set中
参数:
set:信号集
signum:某个信号
返回值:
包含:1;不包含:0;失败:-1
int sigaction(int signum, const struct sigaction *act,
struct sigaction *oldact);
描述:
指定进程在接收特定信号时采取的操作。
参数:
signum:某个信号
act:用于指定新的信号处理程序。
oldact:用于存储之前的信号处理程序的信息。
struct sigaction {
void (*sa_handler)(int); /*指定信号处理程序的函数指针。可以将其设置为自定义的信号处理函数,或者将其设置为
SIG_DFL 表示使用默认的处理程序,或者将其设置为
SIG_IGN 表示忽略该信号。*/
void (*sa_sigaction)(int, siginfo_t *, void *); /*这个字段也是一个信号处理程序的函数指针,与 sa_handler 字段类似。但与 sa_handler 不同的是,
它可以传递更多的关于信号的信息给信号处理程序。它接收三个参数:
int signum:触发信号的编号
siginfo_t *siginfo:一个指向siginfo_t 结构的指针,它包含有关信号的详细信息,例如发送信号的进程 ID。
void *context:一个指向信号上下文的指针,提供有关信号和进程状态的信息。*/
sigset_t sa_mask; //信号集
int sa_flags; //指定一些标志来控制信号处理的行为,例如是否自动重启被中断的系统调用或是否启用信号处理程序的扩展功能。正常使用设置为0即可
void (*sa_restorer)(void);//一个指向信号上下文的指针,提供有关信号和进程状态的信息。
};
返回值:
成功:0;失败:-1
注意:SIGKILL和SIGSTOP这两个信号不在处理范围内,SIGKILL和SIGSTOP是两个特殊的信号,具有特殊的行为和权力。它们被操作系统保留用于强制终止进程的目的,并且无法被捕捉、阻塞或忽略。由于其特殊性质,不能通过sigaction()系统调用来更改它们的默认处理行为,也无法为它们设置自定义的信号处理程序。
示例程序:
static void sigHandler [[noreturn]] (int sig)
{
switch (sig)
{
case SIGINT:
case SIGQUIT:
case SIGTERM:
case SIGHUP:
default:
}
exit(1);
}
static void setUpUnixSignals(std::vector quitSignals)
{
sigset_t blocking_mask;
sigemptyset(&blocking_mask);//清空信号集
for (auto sig : quitSignals)
sigaddset(&blocking_mask, sig);//将信号添加到信号集
struct sigaction sa;
sa.sa_handler = sigHandler;
sa.sa_mask = blocking_mask;
sa.sa_flags = 0;
for (auto sig : quitSignals)
sigaction(sig, &sa, nullptr);//激活信号集
}
int main()
{
std::vector sigs{SIGQUIT, SIGINT, SIGTERM, SIGHUP};
setUpUnixSignals(sigs);
}