sigaction详解

发布时间:2023-05-19

一、sigaction的使用方法

sigaction是Unix系统中的信号处理函数。该函数用于对信号进行控制。sigaction允许用户更加细致地处理信号。sigaction函数原型如下:

int sigaction(int sig, const struct sigaction * restrict act, struct sigaction * restrict oact);

该函数可以替代signal函数,使用更加灵活。参数sig表示要操作的信号类型,act参数表示要设置的信号处理方式等信息,oact表示之前的信号处理方式等信息。

int sigaction(int signum, const struct sigaction *act, struct sigaction *oldact);

参数signum为信号类型,act表示设置的信号处理方式等信息,oldact表示之前的信号处理方式等信息。 以下是sigaction函数的常规使用流程:

  1. 定义一个struct sigaction类型的变量,其中包括处理该信号的函数指针以及标志位
  2. 调用sigaction函数设置信号处理函数
/*定义struct sigaction类型*/
struct sigaction act;
act.sa_handler = handler; /*指定信号处理函数*/
act.sa_flags = SA_SIGINFO; /*设置标志位*/
sigemptyset(&act.sa_mask); /*清空临时信号集*/
/*使用sigaction函数设置信号处理函数*/
if(sigaction(SIGINT, &act, NULL) < 0){
    perror("sigaction");
    return 1;
}

二、sigaction在哪些地方使用

sigaction一般用于以下三种情况:

  1. 系统调用时的错误处理,例如无法访问内存。
  2. 子进程终止,父进程通过SIGCHLD信号处理函数知道子进程的状态。
  3. 日常程序中常规的中断处理,例如Ctrl+C手动中止程序。

三、sigaction函数讲解

sigaction函数可以细致地控制信号处理方式,下面对该函数的参数进行详细说明:

  • sig:要操作的信号类型。常见信号类型如下:
    • SIGINT:Ctrl+C等中断信号
    • SIGKILL:无法拦截的信号,强制终止程序
    • SIGPIPE:管道破裂
    • SIGTERM:系统发出的终止信号
  • act:signal action,表示设置的信号处理方式。struct 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); /*恢复函数*/
}
  • sa_handler, sa_sigaction:表示处理该信号的函数指针
  • sa_mask:一个信号集,其中应包含任何不能同时出现在信号处理程序中的信号
  • sa_flags:各种标志位的掩码,常见标志位如下:
    • SA_NOCLDSTOP:当子进程停止或恢复运行时,不会产生SIGCHLD信号
    • SA_NOCLDWAIT:当子进程退出时,不会产生SIGCHLD信号
    • SA_NODEFER:进入信号处理函数时不会阻塞该信号,即不会在函数执行期间自动屏蔽该信号
  • sa_restorer:总是被置空,之前应返回一个只有调用错误返回的信号处理程序。现在已经不存在需要其恢复处理的情况,所以该参数已忽略。

四、sigaction函数使用

一个简单的sigaction实例:

#include<signal.h>
#include<stdio.h>
void signal_handler(int sig){
    printf("Hello\n");
}
int main(){
    struct sigaction act;
    act.sa_handler = signal_handler;
    act.sa_flags = 0;
    if(sigaction(SIGALRM, &act, NULL) < 0){
        perror("sigaction");
        return 1;
    }
    while(1){
        printf("World\n");
        sleep(1);
    }
    return 0;
}

运行后,每隔一秒输出一个"World",每隔一秒输出一个"Hello"。在程序运行时输入Ctrl+C,可以中断程序运行,输出一行"Hello"。

五、sigaction如果注册了会退出吗

如果程序的sigaction函数注册的是SIGKILL信号,强制终止程序,则程序会直接退出。但这个信号无法被捕获和处理,因此建议避免使用。

六、小结

本文介绍了sigaction函数的使用方法、应用场景、参数说明、以及实例演示。sigaction函数具有很大的灵活性,可以更细致地控制和处理信号。在实际编程中,可以根据需要设定不同的信号处理方式,提高程序的健壮性和正确性。