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

这篇具有很好参考价值的文章主要介绍了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()设置信号处理函数。文章来源地址https://www.toymoban.com/news/detail-433915.html

到了这里,关于Linux系统调用之signal,sigaction函数 (捕捉指定的信号,自定义/默认处理该信号)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【Linux】信号--信号的捕捉/可重入函数/volatile/SIGCHLD信号

    用户态的的时候,进行以下操作:1.操作系统自身的资源(getpid,waitpid…)2.硬件资源(printf, write,read) 用户为了访问内核或者硬件资源,必须通过系统调用完成访问。实际执行系统调用”人是“进程”,但是身份其实是内核。往往系统调用比较费时间一些,所以尽量避免频繁调用系

    2024年02月04日
    浏览(29)
  • 【Linux】进程信号(完整版) --- 信号产生 信号保存 信号捕捉 可重入函数 volatile SIGCHLD信号等

    🍎 作者: 阿润菜菜 📖 专栏: Linux系统编程 我们想要杀死某个后台进程的时候,无法通过ctrl+c热键终止进程时,我们就会通过kill -9的命令来杀死信号。 查看信号也比较简单,通过 kill -l 命令就可以查看所有信号的种类,虽然最大的信号编号是64,但实际上所有信号只有6

    2024年02月04日
    浏览(38)
  • 【genius_platform软件平台开发】第九十七讲:linux设备驱动中信号(signal函数)的异步通知机制

    意思是: 一旦设备就绪,则主动通知应用程序 ,这样应用程序根本就不需要查询设备状态,这一点非常 类似于硬件上“中断”的概念 ,比较准确的称谓是“ 信号驱动的异步I/O ”。信号是在软件层次上对 中断机制的一种模拟 ,在原理上,一个进程收到一个信号与处理器收到一

    2024年02月08日
    浏览(47)
  • 【Linux】信号捕捉

    用户态:执行用户代码时,进程的状态 内核态:执行OS代码时,进程的状态 1.1关于内核空间与内核态: 进程地址空间分为用户空间(3G)和内核空间(1G),不同进程的内核空间是相同的,通过同一张内核级页表映射到物理内存,当调用系统调用接口或时间片到了需要执行进程切换

    2024年02月14日
    浏览(20)
  • 【Linux】 信号的保存 | 捕捉

    对于信号,主要涉及到信号的产生、保存和捕获,之前谈到了信号的产生,这里主要介绍信号产生后如何进行保存和捕捉处理的原理。 相关概念 实际执行处理信号的动作称为 信号递达Delivery 信号从产生到递达的过程称为 信号未决Pending 进程可以阻塞、忽略某个信号。 被阻塞

    2024年02月21日
    浏览(27)
  • 【Linux】进程信号 --- 信号的产生 保存 捕捉递达

    被爱情困住的是傻子 1. 关于信号这个话题我们其实并不陌生,早在以前的时候,我们想要杀死某个后台进程的时候,无法通过ctrl+c热键终止进程时,我们就会通过kill -9的命令来杀死信号。 查看信号也比较简单,通过kill -l命令就可以查看信号的种类,虽然最大的信号编号是

    2023年04月23日
    浏览(28)
  • 【Linux】信号的保存和捕捉

    我们知道,操作系统是进程的管理者,只有操作系统才有资格向进程发信号,具体点,是给进程的PCB发信号。 更具体点,就是将进程的task_struct中的signal整形的某一个比特位由0置1!!! 那么该信号如何被保存下来呢? 实际执行信号的处理动作称为信号递达(Delivery) 信号从产

    2024年02月05日
    浏览(26)
  • 【Linux】进程信号 -- 信号保存与递达 | 信号捕捉 | 僵尸进程的信号处理方法

    实际执行信号的处理动作称为信号递达(Delivery) 信号从产生到递达之间的状态,称为信号未决(Pending)。 已经收到但未处理的状态 进程可以选择阻塞 (Block )某个信号 被阻塞的信号产生时将保持在未决状态,直到进程解除对此信号的阻塞,才执行递达的动作 注意,阻塞和忽略是

    2024年02月16日
    浏览(38)
  • 【Linux】进程信号 -- 信号产生 | 系统调用、硬件、软件的信号发送

    kill -l 是一个在 Linux 和 Unix 系统中使用的命令,用于列出可用的信号列表。 在Linux和Unix系统中,进程可以通过发送信号来与其他进程或操作系统交互。kill 命令可以向指定的进程发送一个特定的信号,以便对其进行控制,例如终止进程或重新启动进程等。 kill -l 命令会列出可

    2024年02月16日
    浏览(71)
  • Linux进程间通信 - 信号(signal) 与 管道(pipe) 与 消息队列

    什么是进程间通信,就是进程与进程之间进行通信,互相发送消息;可以通过 信号 或者 管道 或者 消息队列 或者 信号量 去通信! 目录 一、信号 1. 信号简介  2. 都有那些信号? 3. 注册信号的函数 1). signal 2). sigaction (项目中强烈推荐使用) 4. 信号发送 1). kill 函数 2). alarm 函

    2024年02月01日
    浏览(25)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包