linux_信号捕捉-signal函数-sigaction函数-sigaction结构体

接上一篇:linux_信号_sigemptyset函数-sigfillset函数-sigaddset函数-sigdelset函数-sigismember函数-sigprocmask函数-sigpending函数

本次来分享linux的信号捕捉,话不多说,上菜:

此博主在CSDN发布的文章目录:【我的CSDN目录,作为博主在CSDN上发布的文章类型导读

信号的处理方式又三种,分别是:
  1.执行默认动作
  2.忽略(丢弃)
  3.捕捉(调用户处理函数)
  本次就来说说信号的捕捉。

1.signal函数

函数作用:
  注册一个信号捕捉函数。
头文件:
  #include <signal.h>
函数原型:
  sighandler_t signal(int signum, sighandler_t handler);
函数参数:
  signum:需要捕捉的信号
  handler:回调函数,需要执行的操作。定义:typedef void (*sighandler_t)(int);
返回值:
  成功:返回信号处理程序的前一个值。
  错误:返回SIG_ERR,设置errno以指示原因。

该函数由ANSI定义,由于历史原因在不同版本的Unix和不同版本的Linux中可能有不同的行为。因此应该尽量避免使用它,取而代之使用sigaction函数。

2.sigaction函数

函数作用:
  修改信号处理动作(通常在Linux用其来注册一个信号的捕捉函数)。
头文件:
  #include <signal.h>
函数原型:
   int sigaction(int signum, const struct sigaction *act, struct sigaction *oldact);
函数参数:
  act:传入参数,新的处理方式。
  oldact:传出参数,旧的处理方式。
返回值:
  成功:0;
  失败:-1,设置errno

2.1.struct sigaction结构体

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_restorer:该元素是过时的,不应该使用,POSIX.1标准将不指定该元素。(弃用)
   sa_sigaction:当sa_flags被指定为SA_SIGINFO标志时,使用该信号处理程序。(很少使用)
重点:
   sa_handler:指定信号捕捉后的处理函数名(即注册函数)。也可赋值为SIG_IGN表忽略 或 SIG_DFL表执行默认动作
   sa_mask: 调用信号处理函数时,所要屏蔽的信号集合(信号屏蔽字)。注意:仅在处理函数被调用期间屏蔽生效,是临时性设置。
   sa_flags:通常设置为0,表使用默认属性。

2.2.信号捕捉特性

  1、进程正常运行时,默认PCB中有一个信号屏蔽字,假定为set,它决定了进程自动屏蔽哪些信号。当注册了某个信号捕捉函数,捕捉到该信号以后,要调用该函数。而该函数有可能执行很长时间,在这期间所屏蔽的信号不由set来指定。而是用sa_mask来指定。调用完信号处理函数,再恢复为set。
  2、XXX信号捕捉函数执行期间,XXX信号自动被屏蔽。
  3、阻塞的常规信号不支持排队,产生多次只记录一次。

3.例子-捕捉ctrl-c信号

#include <signal.h>
#include <stdio.h>
#include <errno.h>
#include <stdlib.h>
#include <unistd.h>

typedef void (*sighandler_t) (int);
//捕捉信号后执行的函数
void catchsigint(int signo)
{
    
    
    printf("-----------------catch\n");
}
int main(void)
{
    
    
    sighandler_t handler;
	//捕捉ctrl+c信号,在当前进程收到ctrl+c信号时执行do_sig函数
    handler = signal(SIGINT, catchsigint);//捕捉信号
    if (handler == SIG_ERR) 
	{
    
    
        perror("signal error");
        exit(1);
    }
    while (1);
    return 0;
}

4.例子sigaddset函数-体现信号捕捉特性第一条

//测试捕捉函数阻塞时再发送信号给该进程情况
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
/*自定义的信号捕捉函数*/
void sig_int(int signo)
{
    
    
	printf("catch signal SIGINT\n");//单次打印
    sleep(5);//阻塞期间,向该进程发送其它信号必须得等捕捉函数执行完才响应
    printf("----slept 5 s\n");
}
int main(void)
{
    
    
	struct sigaction act;		
	act.sa_handler = sig_int;
	act.sa_flags = 0;
	sigemptyset(&act.sa_mask);		//信号集合清零
    sigaddset(&act.sa_mask, SIGQUIT);//屏蔽ctrl+c信号
	sigaction(SIGINT, &act, NULL);//注册信号
	while(1);//让主进程阻塞
	return 0;
}
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <signal.h>
void docatch(int signo)
{
    
    
    printf("%d signal is catched\n", signo);
    sleep(5);
    printf("-------finish------\n");
}
int main(void)
{
    
    
    int ret;
    struct sigaction act;
    act.sa_handler = docatch;
    sigemptyset(&act.sa_mask);
    sigaddset(&act.sa_mask, SIGQUIT);
    act.sa_flags = 0;  //默认属性   信号捕捉函数执行期间,自动屏蔽本信号

    ret = sigaction(SIGINT, &act, NULL);
    if (ret < 0) {
    
    
        perror("sigaction error");
        exit(1);
    }
    while (1);
    return 0;
}

以上就是本次的分享了,希望对大家有所帮助。

猜你喜欢

转载自blog.csdn.net/qq_44177918/article/details/130278570