写在前面:小生纯业余选手,开此博仅仅是为了积累,纯当笔记来用。如有看官光临小生博客,请不要相信我的代码就是正确的。如果您发现了错误也恳请耽误您一点时间,请您在下面指出来,不胜感激!
如果发现一些笔记的说法完全是错误的请建议我删除!
如下代码介绍sigprocmask,sigsuspend,sigpending用法,有点糊涂先记着
每个进程都有一个用来描述哪些信号递送到进程时将被阻塞的信号集,该信号集中的所有信号在递送到进程后都将被阻塞。下面是与信号阻塞相关的几个函数:
#include <signal.h> int sigprocmask(int how, const sigset_t *set, sigset_t *oldset)); int sigpending(sigset_t *set)); int sigsuspend(const sigset_t *mask));
sigprocmask()函数能够根据参数how来实现对信号集的操作,操作主要有三种:
参数how | 进程当前信号集 |
---|---|
SIG_BLOCK | 在进程当前阻塞信号集中添加set指向信号集中的信号 |
SIG_UNBLOCK | 如果进程阻塞信号集中包含set指向信号集中的信号,则解除对该信号的阻塞 |
SIG_SETMASK | 更新进程阻塞信号集为set指向的信号集 |
sigpending(sigset_t *set))获得当前已递送到进程,却被阻塞的所有信号,在set指向的信号集中返回结果。
sigsuspend(const sigset_t *mask))用于在接收到某个信号之前, 临时用mask替换进程的信号掩码, 并暂停进程执行,直到收到信号为止。sigsuspend 返回后将恢复调用之前的信号掩码。信号处理函数完成后,进程将继续执行。该系统调用始终返回-1,并将errno设置为EINTR。
#include<stdio.h>
#include<stdlib.h>
#include<signal.h>
#include<unistd.h>
void handle(int s)
{
printf("handling signal^^^^\n");
sleep(2);
printf("handling signal over\n");
}
void handle1(int s)
{
printf("handling SIGUSR1\n");
sleep(2);
printf("handling SIGUSR1 over\n");
}
void handle2(int s)
{
printf("handling SIGUSR2\n");
sleep(2);
printf("handling SIGUSR2 over\n");
}
int main()
{
printf("%d\n",getpid());
sigset_t sigs,sigt,sigu;
sigemptyset(&sigs);
sigemptyset(&sigt);
sigemptyset(&sigu);
sigaddset(&sigs,SIGINT);
sigaddset(&sigs,SIGUSR2);
sigaddset(&sigt,SIGUSR1);
signal(SIGINT,handle);
signal(SIGUSR1,handle1);
signal(SIGUSR2,handle2);
sigprocmask(SIG_BLOCK,&sigs,0);
for(int i = 0;i < 10;i++)
{
printf("breaking %d wall\n",i);
sleep(5);
printf("breaking%d wall over\n",i);
sigsuspend(&sigt);
}
printf("all is over\n");
sigprocmask(SIG_UNBLOCK,&sigs,0);
return 0;
}</span></span>
与上一段代码对比着分析SIGUSR1这个信号的被处理方式。
<span style="font-size:18px;"><span style="font-size:18px;">#include<stdio.h>
#include<stdlib.h>
#include<signal.h>
#include<unistd.h>
void handle(int s)
{
printf("handling signal^^^^\n");
sleep(2);
printf("handling signal over\n");
}
void handle1(int s)
{
printf("handling SIGUSR1\n");
sleep(2);
printf("handling SIGUSR1 over\n");
}
void handle2(int s)
{
printf("handling SIGUSR2\n");
sleep(2);
printf("handling SIGUSR2 over\n");
}
int main()
{
printf("%d\n",getpid());
sigset_t sigs,sigt,sigu;
sigemptyset(&sigs);
sigemptyset(&sigt);
sigemptyset(&sigu);
sigaddset(&sigs,SIGINT);
sigaddset(&sigs,SIGUSR2);
sigaddset(&sigt,SIGUSR1);
signal(SIGINT,handle);
signal(SIGUSR1,handle1);
signal(SIGUSR2,handle2);
sigprocmask(SIG_BLOCK,&sigs,0);
for(int i = 0;i < 20;i++)
{
printf("breaking %d wall\n",i);
sleep(5);
printf("breaking%d wall over\n",i);
sigpending(&sigu);
if(sigismember(&sigu,SIGINT) || sigismember(&sigu,SIGUSR2)||sigismember(&sigu,SIGUSR1))
{
sigsuspend(&sigt);
}
}
printf("all is over\n");
sigprocmask(SIG_UNBLOCK,&sigs,0);
return 0;
}
</span></span>
sigsuspend使原来被屏蔽信号恢复,使suspend第一个参数中的集合中的信号被屏蔽(第二段代码好像违背这一说法),当某个信号处理函数处理完毕后,sigsuspend重新屏蔽被他恢复的信号之后返回。
在信号处理函数被调用的时候,可能会有信号干扰正在被调用的信号处理函数(信号处理函数默认的屏蔽正在处理的信号
sigaction与signal的作用类似,sigqueue与kill作用类似用于发送信号
sigaction绑定的信号处理函数有保护层,当信号处理函数被调用时可以屏蔽指定的信号;sigqueue可以在发送信号的时候发送数据过去。
以下代码说明sigaction的用法
<span style="font-size:18px;">#include<stdio.h>
#include<signal.h>
#include<unistd.h>
void handle(int s)
{
printf("OOOOK\n");
sleep(5);
printf("KOOOO\n");
}
int main()
{
printf("%d\n",getpid());
struct sigaction act = { 0 };
act.sa_handler = handle;
sigemptyset(&act.sa_mask);
sigaddset(&act.sa_mask,SIGINT);
act.sa_flags = SA_SIGINFO;
sigaction(SIGUSR1,&act,0);
while(1);
return 0;
} </span>
通过以下代码可以对上面进程发送信号相当于kill
#include<stdio.h>
#include<signal.h>
#include<unistd.h>
int main()
{
union sigval val;
sigqueue(2222,SIGUSR1,val);
return 0;
}
sigaction的另一种使用方法,在发送信号的同时可以发送数据(数据包括整型数据和指针型数据,在多个进程间发数据时指针数据可能不是我们想要的)
#include<stdio.h>
#include<signal.h>
#include<unistd.h>
void handle_1(int s,siginfo_t* info,void *d)
{
printf("OOOOK:%d\n",info->si_int);
sleep(5);
printf("KOOOO\n");
}
int main()
{
printf("%d\n",getpid());
struct sigaction act = { 0 };
//act.sa_handler = handle;
act.sa_sigaction = handle_1;
sigemptyset(&act.sa_mask);
sigaddset(&act.sa_mask,SIGINT);
act.sa_flags = SA_SIGINFO;
sigaction(SIGUSR1,&act,0);
while(1);
return 0;
}
这里的sigaction能在信号处理函数进行的时候屏蔽信号的功能来自于sigaction函数的第二个参数
以下代码通过sigqueue函数给以上进程发送信号和数据
#include<stdio.h>
#include<signal.h>
#include<unistd.h>
int main()
{
union sigval val;
val.sival_int = 66;
sigqueue(2495,SIGUSR1,val);
return 0;
}