Linux系统调用之signal,sigaction函数 (捕捉指定的信号,自定义/默认处理该信号)

前言

如果,想要深入的学习Linux系统调用中的signal,sigaction函数,还是需要去自己阅读Linux系统中的帮助文档。

具体输入命令:

man 2 signal/sigaction

即可查阅到完整的资料信息。

signal 函数

signal()是一个用于处理Unix和类Unix操作系统(如Linux)中的信号的系统调用。信号是用于在进程间或者进程内部传递通知或者异常事件的机制。信号可以由用户按下某个键、硬件异常、软件中断或者其他进程产生。signal()系统调用允许进程捕获、忽略或者改变特定信号的默认处理行为。

函数原型:

#include <signal.h> //使用此函数需导入此头文件

//该行代码定义了一个名为 sighandler_t 的新类型,
//这个新类型可以指向一个函数,函数无返回值,只有一个 int 类型的参数。
typedef void (*sighandler_t)(int);
sighandler_t signal(int signum, sighandler_t handler);

参数:

  • int signum:指定要处理的信号。例如:SIGINT(终端中断)、SIGTERM(终止信号)等。
  • sighandler_t handler:一个函数指针,用于处理特定的信号。可以是一个用户定义的函数,或者特殊值SIG_IGN(忽略信号)和SIG_DFL(使用默认处理行为)。

返回值:

  • 如果成功,signal()返回之前的信号处理函数指针;否则,返回SIG_ERR,并设置errno以表示错误原因。

示例:

  • 下面是一个简单的C程序,使用signal()捕获SIGINT信号(当用户按下Ctrl+C时产生)并执行自定义处理函数。
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <unistd.h>

/*
	在 C 语言中,函数的名称就是指向函数的指针,
	因此 sigint_handler 代表函数自身的指针。
	在这个程序中,我们希望将 sigint_handler 函数指针传递给 signal 函数,
	使得 signal 函数在接收到 SIGINT 信号时,
	能够调用到 sigint_handler 函数来处理该信号。
*/
void sigint_handler(int sig) {
    printf("捕获到信号 %d\n", sig);
}

int main() {
    signal(SIGINT, sigint_handler);

    while (1) {
        printf("等待信号...\n");
        sleep(1);
    }

    return 0;
}
  • 这个程序运行起来后,会每隔一秒循环输出等待信号…,你需要手动 Ctrl+C, 这个时候,这个进程捕捉到了这个SIGINT信号(也就是signal函数捕捉到了SIGINT信号),然后就会执行自定义的sigint_handler这个函数,而不是执行SIGINT信号默认执行的内容。

  • 我们sigint_handler这个函数的作用是输出一句话,也就是说,用户每按一次Ctrl + C,就会输出
    捕获到信号 SIGINT ,然后继续每隔一秒输出一次 等待信号…

请注意,signal()在不同的Unix和类Unix系统中的行为可能会有所不同。对于可移植性和更多功能,推荐使用sigaction()系统调用。

sigaction()函数

sigaction()是一个Linux系统调用,用于处理和控制信号。相比signal()函数,sigaction()提供了更强大且具有可移植性的信号处理能力。sigaction()可以让你定义捕获信号时的行为,包括设置信号处理函数和信号处理选项。

函数原型:

#include <signal.h> // 使用此函数,需导入此系统调用

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

参数:

  • int signum:指定要处理的信号,例如:SIGINT(终端中断)、SIGTERM(终止信号)等。
  • const struct sigaction *restrict act:一个指向sigaction结构体的指针,该结构体包含信号处理函数和信号处理选项。如果为NULL,则不会改变信号的处理行为。
    struct sigaction *restrict oldact:一个指向sigaction结构体的指针,用于存储信号原有的处理行为。如果为NULL,则不会返回信号原有的处理行为。

返回值:

  • 成功时,返回0;
  • 失败时,返回-1,并设置errno以表示错误原因。

sigaction结构体:

struct sigaction {
    void (*sa_handler)(int);        // 信号处理函数,常用
    void (*sa_sigaction)(int, siginfo_t *, void *); // 带有信号信息的信号处理函数,不常用
    sigset_t sa_mask;               // 在信号处理函数执行期间屏蔽的信号集
    int sa_flags;                   // 控制信号处理行为的标志位,决定你到底是使用sa_handler还是sa_sigaction处理函数。
    void (*sa_restorer)(void);      // 已过时,不建议使用
};
  • 在这里我觉得我得解释一下这个sa_mask,这个是一个临时的阻塞信号集,它的作用仅仅是在执行某个信号的时候,才会去阻塞信号集中的信号,在除了执行某个信号的其他时间里,不会阻塞任何信号。

示例:

  • 下面是一个简单的C程序,使用sigaction()捕获SIGINT信号(当用户按下Ctrl+C时产生)并执行自定义处理函数。
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <unistd.h>

void sigint_handler(int sig) {
    printf("捕获到信号 %d\n", sig);
}

int main() {
    struct sigaction sa;

    sa.sa_handler = sigint_handler;
    sigemptyset(&sa.sa_mask);
    sa.sa_flags = 0;

    if (sigaction(SIGINT, &sa, NULL) == -1) {
        perror("sigaction");
        exit(EXIT_FAILURE);
    }

    while (1) {
        printf("等待信号...\n");
        sleep(1);
    }

    return 0;
}

在这个示例中,我们设置了一个自定义的信号处理函数sigint_handler,用于在接收到SIGINT信号时执行。我们使用sigemptyset()初始化sa_mask,以防止在信号处理函数执行期间阻塞任何其他信号。sa_flags设置为0,表示我们使用默认的信号处理行为。最后,调用sigaction()设置信号处理函数。

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

阿宋同学

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值