[Linux] signal and sigaction two signal capture functions

The usage of sigaction is more complicated, but sigaction is generally used. Signal may have different usage changes according to different standards. sigaction is relatively stable and has only one fixed standard.

signal signal capture function

In the previous article ( [Linux] alarm function and setitimer function ), I used the setitimer function to implement the timing function. The first time was printing after 3 seconds, and then every 2 seconds.

But when the sample code was executed, it was found that it was only printed after 3 seconds, but not every two seconds. This is because the first parameter of the setitimer function in my sample code is ITIMER_REAL (real time). When the time arrives, SIGALRM is sent to the process, and the process stops after receiving the signal. So I don’t see periodic execution printing.

So I need to capture the signal received by the process to prevent the process from automatically terminating after receiving the signal.

1. Function analysis

/*
    #include <signal.h>
    typedef void (*sighandler_t)(int);
    sighandler_t signal(int signum, sighandler_t handler);
        - 功能:设置某个信号的捕捉行为
        - 参数:
            - signum: 要捕捉的信号
            - handler: 捕捉到信号要如何处理
                - SIG_IGN : 忽略信号
                - SIG_DFL : 使用信号默认的行为
                - 回调函数 :  这个函数是内核调用,程序员只负责写,捕捉到信号后如何去处理信号。
                回调函数:
                    - 需要程序员实现,提前准备好的,函数的类型根据实际需求,看函数指针的定义
                    - 不是程序员调用,而是当信号产生,由内核调用
                    - 函数指针是实现回调的手段,函数实现之后,将函数名放到函数指针的位置就可以了。

        - 返回值:
            成功,返回上一次注册的信号处理函数的地址。第一次调用返回NULL
            失败,返回SIG_ERR,设置错误号
            
    SIGKILL SIGSTOP不能被捕捉,不能被忽略。
*/

2. Code examples

#include <sys/time.h>
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>

void myalarm(int num) {
    
    
    printf("捕捉到了信号的编号是:%d\n", num);
    printf("xxxxxxx\n");
}

// 过3秒以后,每隔2秒钟定时一次
int main() {
    
    

    // 注册信号捕捉
    // signal(SIGALRM, SIG_IGN);
    // signal(SIGALRM, SIG_DFL);
    // void (*sighandler_t)(int); 函数指针,int类型的参数表示捕捉到的信号的值。
    signal(SIGALRM, myalarm);//myalarm是我们自己定义的回调函数

    struct itimerval new_value;

    // 设置间隔的时间
    new_value.it_interval.tv_sec = 2;
    new_value.it_interval.tv_usec = 0;

    // 设置延迟的时间,3秒之后开始第一次定时
    new_value.it_value.tv_sec = 3;
    new_value.it_value.tv_usec = 0;

    int ret = setitimer(ITIMER_REAL, &new_value, NULL); // 非阻塞的
    printf("定时器开始了...\n");

    if(ret == -1) {
    
    
        perror("setitimer");
        exit(0);
    }

    getchar();

    return 0;
}

Specific process: Print out "The timer started..." immediately, print it for the first time after three seconds, and then print it every two seconds.
Insert image description here

sigaction signal capture function

1. Function analysis

/*

	#include <signal.h>
	int sigaction(int signum, const struct sigaction *act,
							struct sigaction *oldact);
		- 功能:检查或者改变信号的处理。信号捕捉
		- 参数:             
			- signum : 需要捕捉的信号的编号或者宏值(信号的名称)             
			- act :捕捉到信号之后的处理动作             
			- oldact : 上一次对信号捕捉相关的设置,一般不使用,传递NULL
		- 返回值:             
			成功 0             
			失败 -1
			
	struct sigaction {
    
    
	// 函数指针,指向的函数就是信号捕捉到之后的处理函数         
	void     (*sa_handler)(int);
	
	// 不常用         
	void     (*sa_sigaction)(int, siginfo_t *, void *);
	
	// 临时阻塞信号集,在信号捕捉函数执行过程中,临时阻塞某些信号。         
	sigset_t   sa_mask;
	
	// 使用哪一个信号处理对捕捉到的信号进行处理         
	// 这个值可以是0,表示使用sa_handler,也可以是SA_SIGINFO表示使用sa_sigaction         
	int        sa_flags;    
	     
	// 被废弃掉了         
	void     (*sa_restorer)(void);
	};
	
*/

2. Code examples

#include <sys/time.h> 
#include <stdio.h> 
#include <stdlib.h> 
#include <signal.h>
void myalarm(int num) {
    
         
	printf("捕捉到了信号的编号是:%d\n", num);     
	printf("xxxxxxx\n"); 
}

// 过3秒以后,每隔2秒钟定时一次 
int main() {
    
    
	struct sigaction act;
	act.sa_flags = 0;     
	act.sa_handler = myalarm;     
	sigemptyset(&act.sa_mask);  // 清空临时阻塞信号集

	// 注册信号捕捉     
	sigaction(SIGALRM, &act, NULL);

	struct itimerval new_value;      

	// 设置间隔的时间     
	new_value.it_interval.tv_sec = 2;     
	new_value.it_interval.tv_usec = 0;

	// 设置延迟的时间,3秒之后开始第一次定时     
	new_value.it_value.tv_sec = 3;     
	new_value.it_value.tv_usec = 0;

	int ret = setitimer(ITIMER_REAL, &new_value, NULL); // 非阻塞的     
	printf("定时器开始了...\n");

	if(ret == -1) {
    
             
	perror("setitimer");         
	exit(0);     
	}

	// getchar();     
	while(1);      
	return 0; 
}

Insert image description here

The process of kernel realizing signal capture

Insert image description here

Guess you like

Origin blog.csdn.net/mhyasadj/article/details/130790481