版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/s564200489/article/details/50501556
在linux系统编程的学习中,通过信号进行进程简编译是一大重点
本文通过一个实例加强对sigemptyset、sigprocmask的理解
int sigaction(int signum, const struct sigaction *act,struct sigaction *oldact);
其中 signum 为收到的信号
其中
struct sigaction
{
void (*sa_handler)(int); // }
void (*sa_sigaction)(int, siginfo_t *, void *);// } 两个函数指针仅有一个有效
sigset_t sa_mask; //阻塞信号集
int sa_flags; //若sa_flags==0则*sa_handler;有效,若sa_flags==SA_SIGINFO则*sa_sigaction有效
void (*sa_restorer)(void);//扩展
}
其中sigset_t 为一个结构体,信号在int __val[32] 中以掩码储存,有32位二进制数,以对应一位标‘1’来储存对应信号
我们也可以通过
int sigprocmask(int how, const sigset_t *set, sigset_t *oldset);// 在进程阻塞信号集里,增加或删除信号
其中int how 有如下三种参数,均针对oldset
SIG_BLOCK //增加
SIG_UNBLOCK //删除
SIG_SETMASK //先清空进程阻塞集号,再增加
值得一提的是信号在信号集中的存储并非简单赋值,而是以掩码的形式储存,2进制数不同位标‘1’表示不同命令的存储。在此并不详谈。
当进程信号集中存在某一信号SIG***时,向该进程发送此信号则会被阻塞,直至sa_flags对应的函数被执行完成为止。
以下为实例方便理解:
实例一:
#include <stdio.h>
#include <signal.h>
#include <stdlib.h>
#include <unistd.h>
pid_t i,j;
void f(int sig)
{
if(kill(i,SIGINT)<0)
{
perror("kill fail");
}
if(kill(j,SIGINT)<0)
{
perror("kill fail");
}
wait(i,NULL,0);
wait(j,NULL,0);
printf("Parent process exit!\n");
exit(0);
}
void f_1(int sig)
{
printf("Child process 1 is killed by parent!\n");
}
void f_2(int sig)
{
printf("Child process 2 is killed by parent!\n");
}
int main()
{
i = fork();
if(i<0)
{
perror("fork fail");
return -1;
}
else if(i==0)
{
signal(SIGINT,f_1);
pause();
}
else if(i>0)
{
j = fork();
if(j<0)
{
perror("fork fail");
return -1;
}
if(j==0)
{
signal(SIGINT,f_2);//收到SIGINT信号则执行f_2动作
pause();
}
if(j>0)
{
signal(SIGINT,f);
pause();
}
}
}
实例二:
#include<stdio.h>
#include<signal.h>
#include<stdlib.h>
int output(sigset_t set)
{
printf("set.val[0]=%x\n",(int)set.__val[0]);
}
void handler(int sig)
{
int i;
sigset_t sysset;
printf("\n nin hadler sig=%d\n",sig);
sigprocmask(SIG_SETMASK,NULL,&sysset);
output(sysset);
printf("return\n");
}
int main()
{
struct sigaction act;
sigset_t set,sysset,newset;//自定义信号集合
sigemptyset(&set);
sigemptyset(&newset);//清空
sigaddset(&set,SIGUSR1);//向进程阻塞信号集中发送信号SIGUSR1
sigaddset(&newset,SIGUSR2);
printf("\nadd sigusr1,the value of set");
output(set);//测试
printf("\nadd sigusr2,the value of newset");
output(newset);
printf("\nafter set proc block set ,and then read to sysset\n");
sigprocmask(SIG_SETMASK,&set,NULL);
//将系统阻塞信号集清空,然后拷贝信号集set的内容到系统阻塞信号集中;
sigprocmask(SIG_SETMASK,NULL,&sysset);
//将信号集sysset中的内容清空,然后拷贝系统阻塞信号集中的内容到sysset
printf("system mask is:\n");
output(sysset);//测试,此时系统阻塞信号集的内容为SIGUSR1
printf("set mask is:\n");
output(set);
printf("install sigalrm,and the act.sammask is newset(siguser2)\n");
act.sa_handler=handler;//在另一终端中输入kill -SIGUSR1 [该进程pid] 并不会立刻执行该信号相应动作,直到handler函数执行完毕
act.sa_flags=0;
act.sa_mask=newset;
sigaction(SIGALRM,&act,NULL);//pause中断进程,直至收到“SIGALRM”信号重新激活,运行act所包含的动作。
pause();
printf("after exec isr\n");
sigemptyset(&sysset);//清空sysset
sigprocmask(SIG_SETMASK,NULL,&sysset);
output(sysset);
}