Linux系统编程---Signal信号集
0、前言
在上一篇博客笔记文章中,对Linux进程间通信的信号进行了讲解,本章将接着上一篇文章的内容,继续对Linux进程间通信中信号部分的信号集这个小知识点进行梳理。
如果有对Linux系统编程有不了解的地方,欢迎查阅博主的Linux系统编程专栏进行参考学习交流。
系统编程_奔跑的蜗牛!的博客-CSDN博客https://blog.csdn.net/weixin_49337111/category_12952742.html?spm=1001.2014.3001.5482
1、Linux信号集
(1)、什么是信号集?
在 Linux 中,信号集(Signal Set)是一种用于管理和操作信号的数据结构。
信号集是一个包含多个信号的集合,它可以用来表示一组需要被处理、阻塞或忽略的信号。每个信号在信号集中都有对应的标志位,通过对这些标志位的操作,可以方便地对一组信号进行统一的管理。
(2)、信号阻塞与信号忽略有什么区别?
信号响应:收到信号之后,会响应信号的动作。
信号忽略:收到信号之后,直接丢弃这个信号。
信号阻塞:进程在阻塞某一个信号前提下,收到了这个信号,不会马上响应,而是要等到解除阻塞之后,才会响应这个信号。(这个信号没有被响应时,不会丢弃,而是放在一个挂起队列中)
2、信号集处理函数
(1)、 信号集如何定义?
信号集其实就是一个变量,数据类型是: sigset_t。
定义信号集: sigset_t set;
(2)、sigemptyset
//函数功能
用于初始化一个信号集,将信号集中的所有信号都清空,即设置为不包含任何信号。//函数原型
#include <signal.h>int sigemptyset(sigset_t *set);
//函数参数
set:指向要初始化的信号集的指针//函数返回值
成功时返回 0,出错时返回 - 1
(3)、sigfillset
//函数功能
用于将信号集中的所有信号位都设置为 1,即包含所有的信号//函数原型
#include <signal.h>int sigfillset(sigset_t *set);
//函数参数
set:指向要初始化的信号集的指针//函数返回值
成功时返回 0,出错时返回 - 1
(4)、sigaddset
//函数功能
用于将指定的信号添加到信号集中。//函数原型
#include <signal.h>int sigaddset(sigset_t *set, int signum);
//函数参数
set:指向要初始化的信号集的指针
signum:是要添加的信号编号//函数返回值
成功时返回 0,出错时返回 - 1
(5)、sigdelset
//函数功能
用于从信号集中删除指定的信号。//函数原型
#include <signal.h>int sigdelset(sigset_t *set, int signum);
//函数参数
set:指向要初始化的信号集的指针
signum:是要添加的信号编号//函数返回值
成功时返回 0,出错时返回 - 1
(6)、sigismember
//函数功能
用于检查指定的信号是否在信号集中。//函数原型
#include <signal.h>int sigismember(const sigset_t *set, int signum);
//函数参数
set:指向要初始化的信号集的指针
signum:是要添加的信号编号//函数返回值
成功时返回 0,出错时返回 - 1
(7)、信号集程序示例
先清空信号集,再把SIGUSR1、SIGUSR2加入到集合中,判断信号是不是在集合中。
#include <stdio.h>
#include <signal.h>int main(int argc, char*argv[])
{//1)先定义一个信号集变量 sigset_t set;//2) 初始化(清空)sigemptyset(&set); //清空信号集//3)将信号 添加到集合中 SIGUSR1 SIGUSR2sigaddset(&set, SIGUSR1); //在指定的信号集set中,添加一个指定的信号signum到集合中sigaddset(&set, SIGUSR2);//4) 判断 SIGUSR2信号是否在集合中,如果在打印Yes, 否则 打印No// sigismember 信号在集合中 返回1 否则 返回 0if(sigismember(&set, SIGUSR2)){printf("Yes\n"); } else {printf("No\n"); }return 0;
}
3、信号集状态设置
(1)、API接口
//函数功能
用于检查指定的信号是否在信号集中。//函数原型
#include <signal.h>int sigprocmask(int how, const sigset_t *restrict set,sigset_t *restrict oset);//函数参数
how:决定了信号掩码的修改方式SIG_BLOCK:把set信号集中包含的信号添加到当前信号掩码里,简单来说就是添加阻塞信号。SIG_UNBLOCK:从当前信号掩码中移除set信号集中包含的信号,也就是解除对这些信号的阻塞。SIG_SETMASK:直接用set信号集来替换当前的信号掩码。
set:它指向一个信号集如果how是SIG_BLOCK,则会阻塞这个信号集中的信号;如果how是SIG_UNBLOCK,则会解除对这些信号的阻塞;如果how为SIG_SETMASK,当前信号掩码就会被设置成这个信号集的内容。
oset:它指向一个信号集,用于保存调用该函数之前的信号掩码。如果不需要这个功能,可以把它设置为NULL。//函数返回值
成功时返回 0;出错时返回 - 1,并设置errno来指示具体的错误原因。
sigset set;
信号 -> set
sigprocmask(SIG_BLOCK,&set,NULL); -> 设置为阻塞
...
sigprocmask(SIG_UNBLOCK,&set,NULL); -> 解除阻塞
(2)、程序示例
#include<stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdlib.h>#include <string.h>
#include <sys/wait.h>
#include <signal.h>void signalHandle(int signum)
{printf("捕捉到%d信号,去执行别的事情.....\n",signum);int cnt = 5;while(cnt--){sleep(1);printf("我正在清理 垃圾...%d\n",cnt);}
}//SIGINT
int main(int argc,char**argv) // ./a.out 46725
{//将SIGUSR2 信号 设置 一个信号响应函数signal(SIGUSR2,signalHandle);signal(60,signalHandle);//1、先定义一个信号集合变量 ---数组 sigset_t set;//2、清空 信号集合变量 -----数组清空sigemptyset(&set);//3、将你想要设置的信号 一个个 地加入 到 集合变量中 --数组中每个元素 挨个进行赋值 sigaddset(&set,SIGUSR1); sigaddset(&set,SIGUSR2);sigaddset(&set,60);//将上面的信号集合set中的所有信号 设置 为 阻塞状态sigprocmask(SIG_BLOCK, &set,NULL);int cnt = 30;while(cnt--){sleep(1);printf("[%d]主进程正在执行很重要任务%d.....\n",getpid(),cnt);}//等上面很重要的事情 完成了,再解除阻塞 ,响应信号sigprocmask(SIG_UNBLOCK, &set,NULL);return 0;
}
在上述程序运行中,使用kill命令,对该进程发送信号,在信号集解除阻塞状态后,开始响应。
kill -60 6374
kill -SIGUSR2 6374