【Linux】signal 和 sigaction 两个信号捕捉函数

news2025/1/13 13:08:42

目录

  • signal 信号捕捉函数
      • 1、函数解析
      • 2、代码示例
  • sigaction 信号捕捉函数
      • 1、函数解析
      • 2、代码示例
  • 内核实现信号捕捉的过程

sigaction的用法要复杂一些,但一般都是用sigaction,signal依据不同的标准可能有不同的用法变化,sigaction比较稳定,只有一种固定的标准

signal 信号捕捉函数

在上一篇文章中(【Linux】alarm 函数和 setitimer 函数),我使用了 setitimer 函数来实现定时的功能,首次是在3秒后打印,然后每隔2秒打印一次。

但是当执行了示例代码的时候,发现只是在3秒后进行了打印,却没有每隔两秒打印一次。这是因为我在示例代码中setitimer 函数的第一个参数为ITIMER_REAL(真实时间),当时间到达就会向进程发送 SIGALRM ,而进程在接收到该信号后就停止了。所以没有看到周期性的执行打印

所以我需要对进程收到的信号进行捕捉,防止进程在接收到该信号后就自动终止了

1、函数解析

/*
    #include <signal.h>
    typedef void (*sighandler_t)(int);
    sighandler_t signal(int signum, sighandler_t handler);
        - 功能:设置某个信号的捕捉行为
        - 参数:
            - signum: 要捕捉的信号
            - handler: 捕捉到信号要如何处理
                - SIG_IGN : 忽略信号
                - SIG_DFL : 使用信号默认的行为
                - 回调函数 :  这个函数是内核调用,程序员只负责写,捕捉到信号后如何去处理信号。
                回调函数:
                    - 需要程序员实现,提前准备好的,函数的类型根据实际需求,看函数指针的定义
                    - 不是程序员调用,而是当信号产生,由内核调用
                    - 函数指针是实现回调的手段,函数实现之后,将函数名放到函数指针的位置就可以了。

        - 返回值:
            成功,返回上一次注册的信号处理函数的地址。第一次调用返回NULL
            失败,返回SIG_ERR,设置错误号
            
    SIGKILL SIGSTOP不能被捕捉,不能被忽略。
*/

2、代码示例

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

void myalarm(int num) {
    printf("捕捉到了信号的编号是:%d\n", num);
    printf("xxxxxxx\n");
}

// 过3秒以后,每隔2秒钟定时一次
int main() {

    // 注册信号捕捉
    // signal(SIGALRM, SIG_IGN);
    // signal(SIGALRM, SIG_DFL);
    // void (*sighandler_t)(int); 函数指针,int类型的参数表示捕捉到的信号的值。
    signal(SIGALRM, myalarm);//myalarm是我们自己定义的回调函数

    struct itimerval new_value;

    // 设置间隔的时间
    new_value.it_interval.tv_sec = 2;
    new_value.it_interval.tv_usec = 0;

    // 设置延迟的时间,3秒之后开始第一次定时
    new_value.it_value.tv_sec = 3;
    new_value.it_value.tv_usec = 0;

    int ret = setitimer(ITIMER_REAL, &new_value, NULL); // 非阻塞的
    printf("定时器开始了...\n");

    if(ret == -1) {
        perror("setitimer");
        exit(0);
    }

    getchar();

    return 0;
}

具体过程:立刻打印出"定时器开始了…",隔三秒后打印处第一次,随后每隔两秒打印一次
在这里插入图片描述

sigaction 信号捕捉函数

1、函数解析

/*

	#include <signal.h>
	int sigaction(int signum, const struct sigaction *act,
							struct sigaction *oldact);
		- 功能:检查或者改变信号的处理。信号捕捉
		- 参数:             
			- signum : 需要捕捉的信号的编号或者宏值(信号的名称)             
			- act :捕捉到信号之后的处理动作             
			- oldact : 上一次对信号捕捉相关的设置,一般不使用,传递NULL
		- 返回值:             
			成功 0             
			失败 -1
			
	struct sigaction {
	// 函数指针,指向的函数就是信号捕捉到之后的处理函数         
	void     (*sa_handler)(int);
	
	// 不常用         
	void     (*sa_sigaction)(int, siginfo_t *, void *);
	
	// 临时阻塞信号集,在信号捕捉函数执行过程中,临时阻塞某些信号。         
	sigset_t   sa_mask;
	
	// 使用哪一个信号处理对捕捉到的信号进行处理         
	// 这个值可以是0,表示使用sa_handler,也可以是SA_SIGINFO表示使用sa_sigaction         
	int        sa_flags;    
	     
	// 被废弃掉了         
	void     (*sa_restorer)(void);
	};
	
*/

2、代码示例

#include <sys/time.h> 
#include <stdio.h> 
#include <stdlib.h> 
#include <signal.h>
void myalarm(int num) {     
	printf("捕捉到了信号的编号是:%d\n", num);     
	printf("xxxxxxx\n"); 
}

// 过3秒以后,每隔2秒钟定时一次 
int main() {
	struct sigaction act;
	act.sa_flags = 0;     
	act.sa_handler = myalarm;     
	sigemptyset(&act.sa_mask);  // 清空临时阻塞信号集

	// 注册信号捕捉     
	sigaction(SIGALRM, &act, NULL);

	struct itimerval new_value;      

	// 设置间隔的时间     
	new_value.it_interval.tv_sec = 2;     
	new_value.it_interval.tv_usec = 0;

	// 设置延迟的时间,3秒之后开始第一次定时     
	new_value.it_value.tv_sec = 3;     
	new_value.it_value.tv_usec = 0;

	int ret = setitimer(ITIMER_REAL, &new_value, NULL); // 非阻塞的     
	printf("定时器开始了...\n");

	if(ret == -1) {         
	perror("setitimer");         
	exit(0);     
	}

	// getchar();     
	while(1);      
	return 0; 
}

在这里插入图片描述

内核实现信号捕捉的过程

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/557977.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

易基因:全基因组DNA甲基化分析揭示DNMT1在斑马鱼模型听觉系统发育中的作用 | 胚胎发育

大家好&#xff0c;这里是专注表观组学十余年&#xff0c;领跑多组学科研服务的易基因。 听力障碍通常与内耳发育不全或损伤有关&#xff0c;是影响生活质量的严重健康问题。因此研究听觉器官发生过程中的关键基因对于探索听力损伤的潜在策略至关重要。斑马鱼模型在理解内耳发…

C++ Primer笔记——查找算法

目录 一.简单查找 ①find(first, last, val); ②find_if & find_if_not ③count & count_if ④all_of & any_of & none_of 二.重复值的查找 ①adjacent_find(first, end); ②search_n(first, end, count, val); 三.查找子序列 ①search(first1, end1,…

基于html+css的图展示86

准备项目 项目开发工具 Visual Studio Code 1.44.2 版本: 1.44.2 提交: ff915844119ce9485abfe8aa9076ec76b5300ddd 日期: 2020-04-16T16:36:23.138Z Electron: 7.1.11 Chrome: 78.0.3904.130 Node.js: 12.8.1 V8: 7.8.279.23-electron.0 OS: Windows_NT x64 10.0.19044 项目…

Redis事务和Redis管道

什么是Redis事务:Redis事务是指将多条命令加入到队列里面&#xff0c;一次批量执行多条命令&#xff0c;每一条命令会按顺序执行&#xff0c;在事务执行过程中不会受到客户端所传入的命令请求的影响 1)单独的隔离操作:Redis的事务仅仅保证事务 里面的操作会被连续独占的执行&am…

【Rust 日报】2023-05-21 Helix 23.05发布

Helix 23.05发布 Helix 是个文本编辑器&#xff1a; 新版本功能&#xff1a; 为 LSP 引用请求添加一个配置选项&#xff0c;用于排除声明&#xff08;&#xff03;6886&#xff09;。根据文件扩展名和 shebang 启用语言注入&#xff08;&#xff03;3970&#xff09;。通过最近…

Vision-CAIR/MiniGPT-4:使用先进的大型语言模型增强视觉-语言理解

Vision-CAIR/MiniGPT-4&#xff1a;使用先进的大型语言模型增强视觉-语言理解 摘要 视觉-语言理解是人工智能领域的一个重要方向&#xff0c;它涉及到图像和文本之间的复杂交互。近年来&#xff0c;大型语言模型&#xff08;LLM&#xff09;在自然语言处理&#xff08;NLP&am…

【PCIE732】基于 Kintex UltraScale 系列FPGA 的2 路40G 光纤通道适配器(5GByte/s 带宽)/XCKU060

板卡概述 PCIE732 是一款基于PCIE 总线架构的高性能数据传输卡&#xff0c;板卡具有1 个PCIex8 主机接口、2 个QSFP40G 光纤接口&#xff0c;可以实现2路QSFP 40G 光纤的数据实时采集、传输。板卡采用Xilinx 的高性能Kintex UltraScale 系列FPGA 作为实时处理器&#xff0c;板…

【Nginx】反向代理

文章目录 Nginx反向代理概述Nginx反向代理的配置语法proxy_passproxy_set_headerproxy_redirect Nginx反向代理实战Nginx的安全控制如何使用SSL对流量进行加密nginx添加SSL的支持Nginx的SSL相关指令生成证书开启SSL实例 反向代理系统调优 Nginx反向代理概述 关于正向代理和反向…

IIC-EEPROM实验

IIC I2C介绍I2C物理层&#xff08;内部结构&#xff09;I2C协议层数据有效性起始和结束信号应答响应时序图 数据传输软件模拟IIC使用方法产生IIC起始信号产生IIC停止信号产生ACK应答产生nack非应答等待应答信号到来IIC发送一个字节IIC读一个字节 AT24C02介绍硬件设计软件设计实…

chatgpt赋能Python-python_if_非

Python中的if非语句在SEO中的重要性 在Python编程中&#xff0c;if非语句是必不可少的一部分。它让程序员能够编写条件语句&#xff0c;根据不同的条件执行不同的代码。但你知道吗&#xff1f;if非语句也可以对SEO&#xff08;搜索引擎优化&#xff09;产生深远的影响。 什么…

cannot read system data from XML file

最近在使用ccs进行debug仿真时&#xff0c;不知道为什么一直报错&#xff0c;或者偶尔能够正常下载程序。一些报错情况如下&#xff1a; One or more sections of your program falls into a memory region that is not writable. Invalid Target Configuration file 有可能…

【容器化应用程序设计和开发】2.7 云原生开发工具和框架

2.7 云原生开发工具和框架 今天我们就简单来讲一下云原生下用到的开发工具和一些基本的框架。云原生开发工具和框架是为了支持现代化的应用程序开发&#xff0c;能够简化云原生应用程序的构建、部署、管理和维护。下面是一些常见的云原生开发工具和框架&#xff1a; Kubernetes…

给初学者的Vue.js项目搭建教程

部分数据来源&#xff1a;ChatGPT 1. 环境准备 在开始创建 Vue.js 项目前&#xff0c;需要保证已经安装了 Node.js&#xff08;建议版本12&#xff09;和 NPM&#xff08;Node.js 自带的包管理工具&#xff09;。 可以执行以下命令确认是否已经安装&#xff1a; node -v np…

数字孪生智慧灯杆,“多杆合一”降本增效

随着智慧城市建设的不断深入&#xff0c;智慧灯杆作为城市基础设施的重要组成部分&#xff0c;正在成为城市智能化和绿色化的重要手段之一。 图扑智慧灯杆系统在城市道路照明领域引入信息化手段&#xff0c;通过构建路灯物联网&#xff0c;实现了现代化的路灯按需维修和按需照…

【1】安装与配置tensorflow

常见深度学习框架市场占有率 1.创建虚拟环境 打开菜单栏里的 点击creat创建 2.激活虚拟环境 打开命令提示符&#xff0c;输入activate tensorflow 可以看到进入tensorflow环境&#xff1a; 3.更换源 为提高下载速度&#xff0c;执行以下命令&#xff1a; pip config set g…

SpringCloud Ribbon和OpenFeign组件的使用加示意图和详细讲解

目录 SpringCloud Ribbon Ribbon 介绍 LB(Load Balance) LB 分类 1. 集中式LB 2. 进程内LB 实例-前面member-consumer 轮询负载访问10000/10002 底层就是Ribbon 默认的轮询负载算法 Ribbon 架构图&机制 Ribbon 机制 Ribbon 常见负载算法 替换负载均衡算法-应用实…

CCS新建工程教程

1.先点击ccs软件&#xff0c;打开一个工作台&#xff1a; 2.点击“Project”菜单&#xff0c;选择“New CCS Project”项目&#xff0c;新建 CCS 工 程 3. ①&#xff1a;我们开发板上使用的 DSP 芯片是 TMS320F28335&#xff0c;所以这里我们选择 TMS320F28335。 ②&#xff…

一文读懂Vite和Webpack的区别?

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 一、webpack是什么&#xff1f;二、webpack如何工作&#xff1f;三、Vite是什么&#xff1f;Vite和Webpack的区别&#xff1f; 提示&#xff1a;以下是本篇文章正文…

【Nginx】负载均衡

文章目录 负载均衡概述负载均衡的原理及处理流程负载均衡常用的处理方式方式一:用户手动选择方式二:DNS轮询方式方式三:四/七层负载均衡 Nginx七层负载均衡的指令upstream指令server指令 Nginx七层负载均衡的实现流程负载均衡状态负载均衡策略负载均衡案例案例一&#xff1a;对…

“多杆合一”降本增效——数字孪生智慧灯杆

随着智慧城市建设的不断深入&#xff0c;智慧灯杆作为城市基础设施的重要组成部分&#xff0c;正在成为城市智能化和绿色化的重要手段之一。 图扑智慧灯杆系统在城市道路照明领域引入信息化手段&#xff0c;通过构建路灯物联网&#xff0c;实现了现代化的路灯按需维修和按需照…