【Linux】Signal Capture

1. How the kernel implements signal capture:

(1) If the signal processing action is a user-defined function, this function is called when the signal is delivered, which is called signal capture.

(2) Example:
The user program registers the SIGQUIT signal handler function sighhandler. The main function is currently being executed, and an interrupt or exception occurs and switches to the kernel state. After the interrupt is processed, it is checked that the signal SIGQUIT is delivered before the main function that returns to user mode. After the kernel decides to return to user mode, it does not restore the context of the main function to continue execution, but executes the sighandler function. The sighandler and main functions use different stack spaces. There is no relationship between calling and being called between them. They are two independent control flows. . After the sighhandler function returns, the special system call sigreturn is automatically executed to enter the kernel state again. If there is no new signal to be delivered, returning to user mode this time is to restore the context of the main function and continue execution.

(3) Capture signal process:
write picture description here

2. Signal capture function:

(1) signal function:
register a signal capture function:

typedef void (*sighandler_t)(int);  
sighandler_t signal(int signum,sighandler_t handler);

This function is defined by ANSI and may behave differently in different versions of Unix and different versions of Linux for historical reasons. Therefore, it should be avoided as much as possible, and the sigaction function should be used instead.

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

void do_sig(int a)
{
    printf("Hi,SIGINT,how do you do!\n");
}

int main()
{   if(signal(SIGINT,do_sig)==SIG_ERR)
    {
        perror("signal");
        exit(1);
    }

    while(1)
    {
        printf("---------------\n");
        sleep(1);
    }

    return 0;
}
//每当捕捉到SIGINT信号就调用do_sig函数处理信号;

Signals can also be caught using:

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

typedef void (*sighandler_t)(int);

void catchsigint(int signo)
{ 
    printf(" handle signal!\n");
}
int main()
{
    sighandler_t handler;

    handler=signal(4,catchsigint);
    if(handler==SIG_ERR)
    {
        perror("signal\n");
        exit(1);
    }
    while(1)
    {
        printf("running...\n");
        sleep(1);
    }
        return 0;
}

(2) sigaction function:
modify the signal processing action (usually used in Linux to register a signal capture function)

#include<signal.h>

int sigaction(int signum,const struct sigaction* act,struct sigaction* oldact);
//成功返回0;  失败返回-1;

act: incoming parameters, the new processing method.
oldact: Outgoing parameters, the old way of handling.

struct sigaction structure

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: This element is obsolete and should not be used, and will not be specified by the POSIX.1 standard.

sa_sigaction: This signal handler is used when sa_flags is specified as the SA_SIGINFO flag.

sa_handler: Specifies the name of the handler function after signal capture (ie, a custom function). Can also be assigned to ignore the SIG_IGN table or perform the default action for the SIG_DFL table.

sa_mask: The set of signals to be masked (signal mask word) when the signal processing function is called. The mask takes effect only while the handler is called, and is a temporary setting.

sa_flags: Usually set to 0, the table uses the default attributes.

Usage example:

/*当执行SIGINT信号处理函数期间 
 *多次收到SIGQUIT信号都将被屏蔽(阻塞) 
 *SIGINT信号处理函数处理完,立刻解除对 
 *SIGQUIT信号的屏蔽,由于没有捕捉该信号, 
 *将立刻执行该信号的默认动作,程序退出 
 */ 
#include<stdio.h>
#include<stdlib.h>
#include<signal.h>
#include<unistd.h>

void sig_int(int signo)
{
    printf("catch signal SIGINT\n");
    sleep(10);
    printf("----wait 10 secons\n");   

}

int main()
{
    struct sigaction act;
    act.sa_handler=sig_int;
    act.sa_flags=0;
    sigemptyset(&act.sa_mask);    //初始化信号集,所有位置0,即不屏蔽任何信号
    sigaddset(&act.sa_mask,SIGQUIT);  //设置屏蔽字,屏蔽SIGQUIT信号

    sigaction(SIGINT,&act,NULL);

    printf("---------------wait signal\n");

    while(1);    //等待接收信号

    return 0;
}

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=324885630&siteId=291194637