linux信号

Linux环境下,一般使用signal函数或者sigaction绑定对特定信号的处理。

signal函数

原型如下:

#include <signal.h>
typedef void (*sighandler_t)(int);
sighandler_t signal(int signum, sighandler_t handler);

signal函数的而作用就是将信号与回调函数绑定在一起。

第一个参数就是信号类型,例如SIGINT(2)等,详细的定义见signal.h头文件中。

第二个参数是函数指针,该函数为一个形参为int,返回值为void的函数,可以将其理解为信号产生医护的回调函数。

返回值:成功返回信号处理程序之前的值,当发生错误时返回 SIG_ERR,并且errno也会被设置。

测试代码:

#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
static void sig_int(int signo)
{
    printf("interrupt!\n");
}
int main(int argc, char **argv)
{

    if (signal(SIGINT, sig_int) == SIG_ERR)
    {
        printf("error 1\n");
        exit(1);
    }
    pause();
    return 0;
}

程序运行以后暂停,当用户按下CTRL+C以后,会打印“Interrupt!”然后退出。

其实,sig_int函数可以根据传递的参数,决定对应的动作,我们可以把该函数绑定多个不同的信号,例如:

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

#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
static void sig_handler(int signo)
{
    switch (signo)
    {
    case SIGINT:
        printf("SIGINT!\n");
        break;

    case SIGTSTP:
        printf("SIGTSTP!\n");
        break;
    case SIGALRM:
        printf("SIGALRM!\n");
        break;
    }
}
int main(int argc, char **argv)
{
    if (signal(SIGINT, sig_handler) == SIG_ERR)
    {
        exit(1);
    }
    if (signal(SIGTSTP, sig_handler) == SIG_ERR)
    {
        exit(1);
    }
    if (signal(SIGALRM, sig_handler) == SIG_ERR)
    {
        exit(1);
    }

    while (1)
    {
        alarm(1);
        pause();
    }
    return 0;
}

使用Ctrl+Z,Ctrl+C可以测试SIGTSTP、SIGINT,AIGALAM是定时产生的,需要退出程序时,使用CTRL+\。

这里再把pause函数说一下:

pause() returns only if a signal is received, in which case the signal is handled, and pause() returns -1 and sets errno to EINTR. If the kernel raises an ignored signal, the process does not wake up.
调用该函数以后,只有信号产生的时候才会返回。

sigaction函数

函数原型:

#include <signal.h>
int sigaction(int signum, const struct sigaction *act,struct sigaction *oldact);

第一个参数同样是信号类型;

第二个和第三个参数是同一类型的结构体,该结构体和函数同名,用来表示对信号类型采取的行为,前一个指向了将被设置的处理方式,后二个用于 保存先前的处理方式 。
其定义如下:

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_handler 和signal中的第二个参数一样,是signum对应的处理函数。

第二个参数sa_sigaction也是signum的处理函数。

第三个参数是指明哪些信号要被屏蔽;

第四个参数决定了在signum产生时,到底是使用sa_handler 还是sa_sigaction作为处理函数;

最后一个参数不使用(The sa_restorer field is not intended for application use. )

 测试代码: 

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

struct sigaction sa;

static void sig_alm(int signo)
{
    printf("sig_alm:sig=%d\n",signo);
    sa.sa_flags = SA_SIGINFO;
}

void sig_alt(int sig, siginfo_t *info, void *ucontext)
{
    printf("sig_alt:sig=%d\n",sig);
    sa.sa_flags = 0;
}

int main(int argc, char **argv)
{

    memset(&sa, 0, sizeof(sa));
    sa.sa_handler = &sig_alm;
    sa.sa_sigaction = &sig_alt;
    //sa.sa_flags = SA_SIGINFO;
    sigaction(SIGALRM, &sa, NULL);
    while(1)
    {
        alarm(1);
        pause();
    }
    return 0;
}

 

posted @ 2021-02-06 15:18  castor_xu  阅读(104)  评论(0编辑  收藏  举报