信号之sigaction函数

杀马特。学长 韩版系。学妹 提交于 2020-03-22 09:42:06

可靠机制,不会恢复默认信号处理程序:

新的信号安装函数sigaction:sigaction函数用于改变进程收到的特定信号后的行为
  int sigaction(int signum,const struct sigaction *act,const struct sigaction *old); //成功返回0,失败返回-1

  struct sigaction{
    void (*sa_handler)(int);

    sigset_t sa_mask;//屏蔽集合
    int sa_flags;
    //可选
    void (*sa_sigaction) (int,siginfo_t*,void*) //与void (*sa_handler)(int)任选其一,这个针对可靠信号
  }
1、第一个参数为信号的值,可以为除SIGKILL以及SIGSTOP外的任何一个特定有效的信号;
2、第二个参数是一个指向结构sigaction的一个实例的指针,在结构sigaction的实例中,指定了对特定
信号的处理,可以为空,进程会以缺省的方式对信号处理;这个结构体包含了对指定信号的处理,信号传导的信息,信号处理函数执行过程中应屏蔽掉哪些函数。
3、第三个参数oldact指向的对象用来保存原来对应信号的处理函数,可以指定oldact为NULL

 

#include<unistd.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>
#include<stdlib.h>
#include<stdio.h>
#include<errno.h>
#include<string.h>

#include<signal.h>
#define ERR_EXIT(m)\
    do\
    {\
        perror(m);\
        exit(EXIT_FAILURE);\
    }while(0)  //宏要求一条语句
void handler(int sig);
int main(int argc,char*argv[])
{
    struct sigaction act;
    act.sa_handler=handler;
    sigemptyset(&act.sa_mask);
    act.sa_flags=0;
    if(sigaction(SIGINT,&act,NULL)<0)
        ERR_EXIT("sigaction error\n");
    for(;;)
        pause();
    return 0;
}

void handler(int sig)//sig是signum
{    
    printf("receive a sig=%d\n",sig);
}

 

linux中signal建立在可靠机制之上(信号在安装完,执行处理函数后,信号处理函数不会自动恢复到默认),用sigaction来模拟实现signal:

#include<unistd.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>
#include<stdlib.h>
#include<stdio.h>
#include<errno.h>
#include<string.h>

#include<signal.h>
#define ERR_EXIT(m)\
    do\
    {\
        perror(m);\
        exit(EXIT_FAILURE);\
    }while(0)  //宏要求一条语句
void handler(int sig);
__sighandler_t my_signal(int sig,__sighandler_t handler);
int main(int argc,char*argv[])
{
    struct sigaction act;
    act.sa_handler=handler;
    sigemptyset(&act.sa_mask);
    act.sa_flags=0;
//    if(sigaction(SIGINT,&act,NULL)<0)
//        ERR_EXIT("sigaction error\n");
    my_signal(SIGINT,handler);
    for(;;)
        pause();
    return 0;
}
__sighandler_t my_signal(int sig,__sighandler_t handler)//signal出错返回SIG_ERR
{
    struct sigaction act;
    struct sigaction oldact;
    act.sa_handler=handler;
    sigemptyset(&act.sa_mask);
    act.sa_flags=0;
    if(sigaction(sig,&act,&oldact)<0)
        return SIG_ERR;
    return oldact.sa_handler;

}

void handler(int sig)//sig是signum
{    
    printf("receive a sig=%d\n",sig);
}

 

sigaction 中sa_mask:指定信号屏蔽字(调用信号处理函数所在的线程的信号屏蔽字中)其他信号如果在信号处理程序过程中到来,则它们会在信号处理函数执行时被阻塞。等到信号处理函数运行完,被屏蔽的信号才会递达。不同于sigprocmask,sigprocmask阻塞的信号,根本不会递达, 只会处于未决状态,不会执行信号处理程序。

 1 #include<unistd.h>
 2 #include<sys/types.h>
 3 #include<sys/stat.h>
 4 #include<fcntl.h>
 5 #include<stdlib.h>
 6 #include<stdio.h>
 7 #include<errno.h>
 8 #include<string.h>
 9 
10 #include<signal.h>
11 #define ERR_EXIT(m)\
12     do\
13     {\
14         perror(m);\
15         exit(EXIT_FAILURE);\
16     }while(0)  //宏要求一条语句
17 void handler(int sig);
18 int main(int argc,char*argv[])
19 {
20     struct sigaction act;
21     act.sa_handler=handler;
22     sigemptyset(&act.sa_mask);
23     act.sa_flags=0;
24     
25     sigaddset(&act.sa_mask,SIGQUIT);
26     if(sigaction(SIGINT,&act,NULL)<0)//若不指定sa_mask,若指定的话,SIGQUIT信号在SIGINT处理程序执行期间都被阻塞。
27         ERR_EXIT("sigaction error\n");
28     for(;;)
29         pause();
30     return 0;
31 }
32 
33 void handler(int sig)//sig是signum。信号处理函数过程中,屏蔽sa_mask
34 {    
35     printf("receive a sig=%d\n",sig);
36     sleep(5);//不设置sa_mask的话,未返回时按ctrl+\直接退出,不能阻塞新的信号。阻塞结束,SIGQUIT信号递达
37 }

 

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!