Linux 信号(三)sigaction函数

时间:2021-04-05 14:42:49

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);
};

类似于signal函数,sigaction可以为某些信号设置回调,这些设置都在struct sigaction中进行

1.void (*sa_handler)(int)信号处理函数
2.void (*sa_sigaction)(int,siginfo_t*,void*)也是信号处理函数,当sa_flagSA_SIGFINFO时将使用该函数

上述两个信号吹函数是互斥的,一次只能使用两个字段中的一个,因此在一些实现中,使用union来存放这两个函数。
siginfo_t结构体中存放了一些信号产生原因的有关信息。

3.sigset_t sa_mask 是一个sigset,可以在信号处理函数执行的时候屏蔽某些信号。

4.int sa_flags 这是一个选项字段。比如说:
SA_RESTART:使被信号打断的系统调用自动重新发起。
SA_NOCLDSTOP:使父进程在它的子进程暂停或继续运行时不会收到 SIGCHLD 信号。
SA_NOCLDWAIT:使父进程在它的子进程退出时不会收到 SIGCHLD 信号,这时子进程如果退出也不会成为僵尸进程。

下面例子说明sigaction函数的部分用法:

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


static void sig_usr(int signo)
{
printf("in signal handler\r\n");
sleep(20);//will not receive SIGINT
}

int main(int argc ,char **argv)
{
struct sigaction sa_usr;

sigset_t mask;
sigemptyset(&mask);
sigaddset(&mask,SIGINT);


sa_usr.sa_handler=sig_usr;
sa_usr.sa_mask=mask;
sa_usr.sa_flags=0;

sigaction(SIGUSR1,&sa_usr,NULL);
pause();

return 0;
}

另外,由于sigacation提供了比signal更多的功能,我们可以使用sigaction来实现signal函数

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

typedef void (*sighandler_t)(int);

sighandler_t MySignal(int signo,sighandler_t handler)
{
struct sigaction act,oact;

sigset_t mask;
sigemptyset(&mask);


act.sa_handler=handler;
act.sa_mask=mask;
act.sa_flags |= SA_RESTART;


if(sigaction(signo,&act,&oact)<0)
return SIG_ERR;

return oact.sa_handler;


}

static void sig_handler(int signo)
{
printf("in sig handler\r\n");
}

int main(int argc, char **argv)
{
MySignal(SIGALRM,sig_handler);
alarm(5);
pause();

return 0;
}