十八、Linux系统编程-信号(五)sigaction和sigqueue

时间:2021-11-11 14:45:17
一、sigaction函数 函数声明:
#include <signal.h>
int sigaction(int signum, const struct sigaction *act,struct sigaction *oldact);
函数参数:
  • 该函数的第一个参数为信号的值,可以为除SIGKILL及SIGSTOP外的任何一个特定有效的信号(为这两个信号定义自己的处理函数,将导致信号安装错误)
  • 第二个参数是指向结构sigaction的一个实例的指针,在结构sigaction的实例中,指定了对特定信号的处理,可以为空,进程会以缺省方式对信号处理
  • 第三个参数oldact指向的对象用来保存原来对相应信号的处理,可指定oldact为NULL。
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);
};
sigaction中的sa_mask会加入到调用进程的进程屏蔽字。屏蔽的信号到达后将阻塞直到注册的信号处理函数执行完成。
和sigprocmask指定的掩码不同的是,sigprocmask屏蔽的信号在根本上被阻塞,和信号处理函数有没有执行完成没有关系。

返回值:成功返回0,失败返回-1

示例:
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>

#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <unistd.h>
#include <signal.h>
#define ERR_EXIT(m) \
do \
{ \
perror(m); \
exit(EXIT_FAILURE); \
}while(0)
void handle(int sig);
__sighandler_t my_signal(int,__sighandler_t);
int main(int argc,char* argv[])
{
//my_signal(SIGINT,handle);
struct sigaction act;
act.sa_handler = handle;
sigemptyset(&act.sa_mask);
act.sa_flags = 0;
sigaddset(&act.sa_mask,SIGINT);
if (sigaction(SIGINT,&act,NULL) < 0)
ERR_EXIT("sigaction error");
for(;;)
pause();
return 0;
}
//implement own signal
__sighandler_t my_signal(int sig,__sighandler_t handler)
{
struct sigaction act;
struct sigaction oldact;
act.sa_handler = handler;
sigemptyset(&act.sa_mask);
act.sa_flags = 0;
if (sigaction(sig,&act,&oldact) < 0)
return SIG_ERR;
return oldact.sa_handler;
}

void handle(int sig)
{
printf("recv a sig=%d\n",sig);
sleep(3);
}

二、sigqueue函数功能:新的发送信号系统调用,主要是针对实时信号提出的支持信号带有参数,与函数sigaction()配合使用函数声明:
#include <signal.h>
int sigqueue(pid_t pid, int sig, const union sigval value);
函数参数:
进程号,信号,传递的数据返回值:成功返回0,失败返回-1

示例:
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <unistd.h>
#include <signal.h>
#define ERR_EXIT(m) \
do \
{ \
perror(m); \
exit(EXIT_FAILURE); \
}while(0)
void handle(int sig,siginfo_t *,void *);
int main(int argc,char* argv[])
{
//my_signal(SIGINT,handle);
struct sigaction act;
act.sa_sigaction = handle;
sigemptyset(&act.sa_mask);
act.sa_flags = SA_SIGINFO;
if (sigaction(SIGINT,&act,NULL) < 0)
ERR_EXIT("sigaction error");
for(;;)
pause();
return 0;
}

void handle(int sig,siginfo_t *info,void *ctx)
{
        printf("recv a sig=%d\n",sig);
        printf("recv value=%d\n",info->si_value.sival_int);
        sleep(3);
}<span style="font-family: Arial, Helvetica, sans-serif;"></span>

信号发送:
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>


#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <unistd.h>
#include <signal.h>
#define ERR_EXIT(m) \
        do \
        { \
                perror(m); \
                exit(EXIT_FAILURE); \
        }while(0)
int main(int argc,char* argv[])
{
        if (argc != 2)
        {
                printf("usage:should 2 para\n");
        }
        union sigval va;
        va.sival_int = 100;
        sigqueue(atoi(argv[1]),SIGRTMIN,va);
        return 0;
}
通过在短时间内发送多个SIGRTMIN信号,也能证明可靠信号是支持排队的。