首先我们知道信号是一个进程对另一个进程进行通知的手段,当我们在通知另一个进程时需要携带数据时(仅限int类型),无参信号就满足不了我们的需求,这个时候我们可以使用带参信号进行携带数据的通知
无参信号:
signal(SIGUSR1, signal_function);//第一个参数是信号编号,第二个参数是一个类似槽函数的东西,函数指针
kill(pid,SIGUSR1);//参数:进程ID,信号
带参信号:
Sigaction-sigqueue
1.先初始化一个sigaction类型的结构体
struct sigaction act;
2.再把带参信号函数(自己声明的函数)给到这个结构体
act.sa_sigaction = sigaction_function;// sigaction_function这个是函数名
struct sigaction { void (*sa_handler)(int); // 指向信号处理函数的指针 void (*sa_sigaction)(int, siginfo_t *, void *); // 用于接收更多关于信号的信息的信号处理函数指针 sigset_t sa_mask; // 在信号处理函数执行期间阻塞的信号集合 int sa_flags; // 控制信号处理的行为 void (*sa_restorer)(void); // 用于兼容旧的信号处理方式,一般不使用 }; |
这边这个结构体中既有带参的函数指针属性,也有不带参的指针属性,sa_flags就是有无带参的标志位 |
3.绑定信号和函数
sigaction(SIGUSR1,&act,NULL);//这个是信号绑定一个结构体,结构体里面有函数
4.发送信号---先准备数据
先准备数据---准备联合体
union sigval val;
val.sival_int = 10001;
5.发送带参信号
sigqueue(pid,SIGUSR1,val);
做完这些很显然还不够,我们为了保证程序的安全性还需要进行一个信号屏蔽的操作
//操作:屏蔽信号
//作用:保护程序,不受外界干扰
//步骤1:创建信号集
sigset_t set;
//初始化信号集
sigemptyset(&set);
//将需要屏蔽的信号添加到信号集中
sigaddset(&set,SIGUSR1);//第一个参数是信号集,第二个参数是把要添加到这个信号集中的信号
sigaddset(&set,SIGUSR2);
//启动信号集
if (sigprocmask(SIG_BLOCK,&set,NULL)<0)//这边第一个参数就是锁住的意思,第二个参数是锁住哪个信号集
{
perror("信号集启动失败");
}
做完这些应该想到那我们如何获取信号携带的参数呢?
答案是在信号处理函数中获取到
//带参信号处理函数
void sigaction_function(int num, siginfo_t*info, void*arg)//void*这个没用,开发人员没写完
{
int x = info->si_int;//要这样取出这个指针里面的值
cout << getpid() << "执行信号处理x = " << x<<"num = " <<num<< endl;//这个num是信号的编号,这边绑定的信号是SIGUSR1对应的是10
//这边可以用不同的num来判断是哪个信号触发的这个函数
//然后可以用num来筛选要做哪一件事情
//因此有多个信号的话只需要写一个函数即可,然后在这个函数里面用信号编号做区分来完成不同的业务就行了
}
int x = info->si_int;//要这样取出这个指针里面的值 要想拿到发送的int的的值只能通过这个方法拿到 |
补充
这个val是一个联合体,也是一个数据结构,里面有一个int的属性和一个void*的属性,但是由于进程建通信的手段不止于信号,有其他更加便捷方法,因此这个void*的这个属性就没被继续完善,因此不能使用用,只能用这个int类型 所以这边发送的信号只能发送int类型的 |