当前位置: 首页 > news >正文

【Linux操作系统】Linux系统编程中信号捕捉的实现

在Linux系统编程中,信号是一种重要的机制,用于实现进程间通信和控制。当某个事件发生时,如用户按下Ctrl+C键,操作系统会向进程发送一个信号,进程可以捕获并相应地处理该信号。本篇博客将介绍信号的分类、捕获与处理方式,以及信号的默认操作。希望通过本篇博客,你能够更好地理解Linux系统编程中信号的概念与应用。
在这里插入图片描述

文章目录

    • 1. 什么是信号?
    • 2. 信号的分类
    • 3. 信号的处理方式
    • 4. 信号的捕获与处理
      • 4.1 `signal`
      • 4.2 `sigaction`
    • 5. 信号的默认操作
    • 总结


1. 什么是信号?

在Linux系统中,信号是一种用于进程间通信和控制的机制。当某个事件发生时,内核会向进程发送一个信号,进程可以选择捕获并处理这个信号,或者使用默认的处理方式。

信号可以由多种事件触发,例如用户按下Ctrl+C键、进程发生错误、子进程退出等。每个信号都有一个唯一的编号,以及一个预定义的默认行为。


2. 信号的分类

  1. 标准信号(Standard Signals):这些信号的编号在1到31之间,是POSIX标准中定义的。例如,SIGINT信号(编号为2)是由用户按下Ctrl+C键触发的,SIGTERM信号(编号为15)是用于终止进程的信号。

  2. 实时信号(Real-time Signals):这些信号的编号在32到63之间,也是POSIX标准中定义的。实时信号提供了更高的优先级和更精确的触发时间。

  3. 自定义信号(User-defined Signals):这些信号可以由用户自定义,其编号大于64。


3. 信号的处理方式

  1. 忽略(Ignore):进程可以选择忽略某个特定的信号,这样当该信号发生时,进程不会做任何处理。但是,某些信号是不能被忽略的,例如SIGKILL和SIGSTOP。

  2. 捕获(Catch):进程可以通过注册信号处理函数来捕获某个信号。当信号发生时,内核会调用注册的信号处理函数来处理该信号。

  3. 执行默认操作(Default Action):每个信号都有一个预定义的默认行为,例如终止进程、终止进程并生成核心转储文件等。


4. 信号的捕获与处理

4.1 signal

作用signal函数用于捕获和处理信号。

原型

#include <signal.h>void (*signal(int signum, void (*handler)(int)))(int);

参数

  • signum:要捕获的信号编号。
  • handler:信号处理函数的指针。

返回值:返回之前对该信号的处理函数的指针。如果出错,则返回SIG_ERR

示例:下面是一个示例,演示如何使用signal函数来捕获和处理SIGINT信号(用户按下Ctrl+C键)。

#include <stdio.h>
#include <signal.h>void sigint_handler(int signum) {printf("Received SIGINT signal\n");
}int main() {// 注册SIGINT信号的处理函数signal(SIGINT, sigint_handler);printf("Press Ctrl+C to send SIGINT signal\n");while (1) {// 无限循环,等待信号的发生}return 0;
}

示例解释

  • 在上面的示例中,我们定义了一个名为sigint_handler的信号处理函数。当接收到SIGINT信号时,该函数会被调用,并打印一条消息。
  • main函数中,我们使用signal函数来注册sigint_handler函数作为SIGINT信号的处理函数。这样,当用户按下Ctrl+C键时,操作系统会发送SIGINT信号给进程,并调用sigint_handler函数来处理该信号。
  • main函数的无限循环中,我们等待信号的发生。这样,进程会一直运行,直到接收到SIGINT信号或其他终止信号为止。
  • 当我们按下Ctrl+C键时,会触发SIGINT信号,进程会调用sigint_handler函数,并打印一条消息。

4.2 sigaction

作用sigaction函数是另一种捕获和处理信号的方法,相比于signal函数,它提供了更多的灵活性和可靠性。

原型

#include <signal.h>int sigaction(int signum, const struct sigaction *act, struct sigaction *oldact);

参数

  • signum:要捕获的信号编号。
  • act:一个指向struct sigaction结构的指针,用于指定新的信号处理方式。
  • oldact:一个指向struct sigaction结构的指针,用于保存之前的信号处理方式。

返回值:若成功,返回0;若出错,返回-1。

示例:下面是一个示例,演示如何使用sigaction函数来捕获和处理SIGINT信号(用户按下Ctrl+C键)。

#include <stdio.h>
#include <signal.h>void sigint_handler(int signum) {printf("Received SIGINT signal\n");
}int main() {struct sigaction sa;sa.sa_handler = sigint_handler;sigemptyset(&sa.sa_mask);sa.sa_flags = 0;// 注册SIGINT信号的处理函数sigaction(SIGINT, &sa, NULL);printf("Press Ctrl+C to send SIGINT signal\n");while (1) {// 无限循环,等待信号的发生}return 0;
}

示例解释

  • 在上面的示例中,我们定义了一个名为sigint_handler的信号处理函数。当接收到SIGINT信号时,该函数会被调用,并打印一条消息。
  • 我们创建了一个struct sigaction结构sa,并将sigint_handler函数指定为信号处理函数。
  • 使用sigemptyset函数初始化了sa.sa_mask,表示在处理SIGINT信号时不需要阻塞其他信号。
  • sa.sa_flags设置为0,表示不需要特殊的标志。
  • 使用sigaction函数将sa结构注册为SIGINT信号的处理方式。
  • main函数的无限循环中,我们等待信号的发生。这样,进程会一直运行,直到接收到SIGINT信号或其他终止信号为止。
  • 当我们按下Ctrl+C键时,会触发SIGINT信号,进程会调用sigint_handler函数,并打印一条消息。

5. 信号的默认操作

如果不捕获某个信号或者捕获的信号处理函数返回,进程会执行该信号的默认操作。

例如,当接收到SIGTERM信号时,进程会默认终止。下面是一个示例,演示了SIGTERM信号的默认操作:

#include <stdio.h>
#include <signal.h>
#include <unistd.h>void sigterm_handler(int signum) {printf("Received SIGTERM signal\n");
}int main() {// 注册SIGTERM信号的处理函数signal(SIGTERM, sigterm_handler);printf("Press Ctrl+C to send SIGTERM signal\n");while (1) {// 无限循环,等待信号的发生}return 0;
}

在上面的示例中,我们捕获了SIGTERM信号并注册了sigterm_handler函数作为处理函数。当接收到SIGTERM信号时,该函数会被调用,并打印一条消息。


总结

信号是Linux系统中用于进程间通信和控制的机制。我们可以通过捕获信号并注册处理函数来实现对信号的处理。在处理信号时,我们可以选择忽略、捕获或执行默认操作。

相关文章:

【Linux操作系统】Linux系统编程中信号捕捉的实现

在Linux系统编程中&#xff0c;信号是一种重要的机制&#xff0c;用于实现进程间通信和控制。当某个事件发生时&#xff0c;如用户按下CtrlC键&#xff0c;操作系统会向进程发送一个信号&#xff0c;进程可以捕获并相应地处理该信号。本篇博客将介绍信号的分类、捕获与处理方式…...

【PHP】基础语法变量常量

文章目录 PHP简介前置知识了解静态网站的特点动态网站特点 PHP基础语法代码标记注释语句分隔(结束)符变量变量的基本概念变量的使用变量命名规则预定义变量可变变量变量传值内存分区 常量基本概念常量定义形式命名规则使用形式系统常量魔术常量 PHP简介 PHP定义&#xff1a;一…...

Failed to resolve: com.github.mcxtzhang:SwipeDelMenuLayout:V1.3.0

在allprojects下的repositories闭包里面添加jcenter()和maven {url https://jitpack.io}&#xff0c;具体可以看你的第三方框架需要添加什么仓库&#xff0c;大多数都只需要上面两个。 我的build.gradle&#xff08;Project&#xff09;完整内容如下&#xff1a; buildscript …...

常用 Python IDE 汇总(非常详细)从零基础入门到精通,看完这一篇就够了

写 Python 代码最好的方式莫过于使用集成开发环境&#xff08;IDE&#xff09;了。它们不仅能使你的工作更加简单、更具逻辑性&#xff0c;还能够提升编程体验和效率。 每个人都知道这一点。而问题在于&#xff0c;如何从众多选项中选择最好的 Python 开发环境。初级开发者往往…...

【Hive】HQL Map 『CRUD | 相关函数』

文章目录 1. Map 增删改查1.1 声明 Map 数据类型1.2 增1.3 删1.4 改1.5 查 2. Map 相关函数2.1 单个Map 3. Map 与 String3.1 Map 转 string3.2 string 转 Map 1. Map 增删改查 1.1 声明 Map 数据类型 语法&#xff1a;map<基本数据类型, 基本数据类型> 注意是<>…...

ELF修复基本工作原理

ELF修复基本工作原理 ELF(Executable and Linkable Format)是一种常见的可执行文件和可链接文件的格式,广泛用于Linux和UNIX系统中。ELF修复是指对ELF文件进行修改或修复,以确保其正确加载和执行。 ELF修复的基本工作原理如下: 识别ELF文件:首先,需要识别和验证目标文…...

matlab实现输出的几种方式(disp函数、fprintf函数、print函数)

matlab实现输出的几种方式&#xff08;disp函数、fprintf函数、print函数&#xff09; 输出为文本、文件、打印 1、disp函数 显示变量的值&#xff0c;如果变量包含空数组&#xff0c;则会返回 disp&#xff0c;但不显示任何内容。 矩阵 A [1 0]; disp(A)结果 字符串 S …...

C/C++数据库编程

文章目录 0. Mysql安装与开发环境配置1. win10 Navicat 连接虚拟机的MySQL需要关闭防火墙2. 由于找不到libmysql.dIl, 无法继续执行代码。重新安装程序可能会解决此问题。3. 测试连接数据库&#xff0c;并插入数据4. C封装MySQL增删改查操作 0. Mysql安装与开发环境配置 MySQL…...

通过python在unity里调用C#接口

log: 背景 最近在做虚拟人底层驱动sdk测试&#xff0c;因为后端使用的是C#,我个人更倾向于python编程辅助测试工作&#xff0c;测试sdk需要通过开发提供的接口方法文档&#xff0c;通过传测试场景参数调用方法进行单元测试 技术&工具 项目语言 C# 项目工具 unity 测试…...

C++笔记之左值与右值、右值引用

C笔记之左值与右值、右值引用 code review! 文章目录 C笔记之左值与右值、右值引用1.左值与右值2.右值引用——关于int&& r 10;3.右值引用——对比int&& r 10;和int& r 10;4.右值引用&#xff08;rvalue reference&#xff09;的概念 1.左值与右值 2.…...

JS逆向-某招聘平台token

前言 本文是该专栏的第56篇,后面会持续分享python爬虫干货知识,记得关注。 通常情况下,JS调试相对方便,只需要chrome或者一些抓包工具,扩展插件,就可以顺利完成逆向分析。目前加密参数的常用逆向方式大致可分为以下几种,一种是根据源码的生成逻辑还原加密代码,一种是补…...

LLMs高效的多 GPU 计算策略Efficient multi-GPU compute strategies

很有可能在某个时候&#xff0c;您需要将模型训练工作扩展到超过一个GPU。在上一个视频中&#xff0c;我强调了当您的模型变得太大而无法适应单个GPU时&#xff0c;您需要使用多GPU计算策略。但即使您的模型确实适合单个GPU&#xff0c;使用多个GPU加速训练也有好处。即使您正在…...

jvm-类加载子系统

1.内存结构概述 类加载子系统负责从文件系统或网络中加载class文件&#xff0c;class文件在文件开头有特定的文件标识 ClassLoader只负责class文件的加载&#xff0c;至于它是否运行&#xff0c;则由Execution Engine决定 加载的类信息存放于一块称为方法区的内存空间&#xff…...

【实例分割】(一)Mask R-CNN详细介绍带python代码

目录 1.&#x1f340;&#x1f340;实例分割定义 2.&#x1f340;&#x1f340;Mask R-CNN 3.&#x1f340;&#x1f340;经典的实例分割算法 4.&#x1f340;&#x1f340;Mask R-CNN python代码 整理不易&#xff0c;欢迎一键三连&#xff01;&#xff01;&#xff01;…...

面试官问我Redis怎么测,我一脸懵逼!

有些测试朋友来问我&#xff0c;redis要怎么测试&#xff1f;首先我们需要知道&#xff0c;redis是什么&#xff1f;它能做什么&#xff1f; redis是一个key-value类型的高速存储数据库。 redis常被用做&#xff1a;缓存、队列、发布订阅等。 所以&#xff0c;“redis要怎么测试…...

【Spring Boot】四种核心类的依赖关系:实体类、数据处理类、业务处理类、控制器类

//1.配置项目环境&#xff0c;创建Spring Boot项目。 //2.数据库设置&#xff0c;配置数据库。 //3.创建实体类&#xff0c;映射到数据库。 //4.创建数据处理层类&#xff0c;Repository //5.创建业务处理类&#xff0c;Service类 //6.创建控制器类&#xff0c;Controller类 Ar…...

opencv 进阶15-检测DoG特征并提取SIFT描述符cv2.SIFT_create()

前面我们已经了解了Harris函数来进行角点检测&#xff0c;因为角点的特性&#xff0c;这些角点在图像旋转的时候也可以被检测到。但是&#xff0c;如果我们放大或缩小图像时&#xff0c;就可能会丢失图像的某些部分&#xff0c;甚至有可能增加角点的质量。这种损失的现象需要一…...

ES5 的构造函数和 ES6 的类有什么区别

文章目录 语法不同方法定义方式不同继承方式不同类内部的this指向不同静态成员定义方式不同访问器属性类的类型检查 在JavaScript中&#xff0c;类和构造函数都被用来创建对象&#xff0c;接下来会从以下几点说说两者的区别&#xff1a; 语法不同 构造函数使用函数来定义类使用…...

AUTOSAR配置与实践(配置篇) 如何条件控制PDU外发

AUTOSAR配置与实践(配置篇)如何条件控制PDU外发 一、需求1.1 需求简要分析1.2 需求进一步分析二、流程实现和具体配置一、需求 需要针对特定的PDU(外发)进行条件控制,这里要通过不同配置字进行PDU是否外发的控制 1.1 需求简要分析 正常PDU分组时分为两组,接收报文组和…...

2023年湖北中级工程师职称申报专业有哪些?甘建二告诉你

中级职称职称申报专业&#xff1a;环境工程、 土木建筑、土建结构、土建监理、土木工程、岩石工程、岩土、土岩方、风景园林、园艺、园林、园林建筑、园林工程、园林绿化、古建筑园林、工民建、工民建安装、建筑、建筑管理、建筑工程、建筑工程管理、建筑施工、建筑设计、建筑装…...

(十)学生端搭建

本次旨在将之前的已完成的部分功能进行拼装到学生端&#xff0c;同时完善学生端的构建。本次工作主要包括&#xff1a; 1.学生端整体界面布局 2.模拟考场与部分个人画像流程的串联 3.整体学生端逻辑 一、学生端 在主界面可以选择自己的用户角色 选择学生则进入学生登录界面…...

Qt Widget类解析与代码注释

#include "widget.h" #include "ui_widget.h"Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget) {ui->setupUi(this); }Widget::~Widget() {delete ui; }//解释这串代码&#xff0c;写上注释 当然可以&#xff01;这段代码是 Qt …...

django filter 统计数量 按属性去重

在Django中&#xff0c;如果你想要根据某个属性对查询集进行去重并统计数量&#xff0c;你可以使用values()方法配合annotate()方法来实现。这里有两种常见的方法来完成这个需求&#xff1a; 方法1&#xff1a;使用annotate()和Count 假设你有一个模型Item&#xff0c;并且你想…...

【决胜公务员考试】求职OMG——见面课测验1

2025最新版&#xff01;&#xff01;&#xff01;6.8截至答题&#xff0c;大家注意呀&#xff01; 博主码字不易点个关注吧,祝期末顺利~~ 1.单选题(2分) 下列说法错误的是:&#xff08; B &#xff09; A.选调生属于公务员系统 B.公务员属于事业编 C.选调生有基层锻炼的要求 D…...

unix/linux,sudo,其发展历程详细时间线、由来、历史背景

sudo 的诞生和演化,本身就是一部 Unix/Linux 系统管理哲学变迁的微缩史。来,让我们拨开时间的迷雾,一同探寻 sudo 那波澜壮阔(也颇为实用主义)的发展历程。 历史背景:su的时代与困境 ( 20 世纪 70 年代 - 80 年代初) 在 sudo 出现之前,Unix 系统管理员和需要特权操作的…...

Python如何给视频添加音频和字幕

在Python中&#xff0c;给视频添加音频和字幕可以使用电影文件处理库MoviePy和字幕处理库Subtitles。下面将详细介绍如何使用这些库来实现视频的音频和字幕添加&#xff0c;包括必要的代码示例和详细解释。 环境准备 在开始之前&#xff0c;需要安装以下Python库&#xff1a;…...

【开发技术】.Net使用FFmpeg视频特定帧上绘制内容

目录 一、目的 二、解决方案 2.1 什么是FFmpeg 2.2 FFmpeg主要功能 2.3 使用Xabe.FFmpeg调用FFmpeg功能 2.4 使用 FFmpeg 的 drawbox 滤镜来绘制 ROI 三、总结 一、目的 当前市场上有很多目标检测智能识别的相关算法&#xff0c;当前调用一个医疗行业的AI识别算法后返回…...

【分享】推荐一些办公小工具

1、PDF 在线转换 https://smallpdf.com/cn/pdf-tools 推荐理由&#xff1a;大部分的转换软件需要收费&#xff0c;要么功能不齐全&#xff0c;而开会员又用不了几次浪费钱&#xff0c;借用别人的又不安全。 这个网站它不需要登录或下载安装。而且提供的免费功能就能满足日常…...

【从零学习JVM|第三篇】类的生命周期(高频面试题)

前言&#xff1a; 在Java编程中&#xff0c;类的生命周期是指类从被加载到内存中开始&#xff0c;到被卸载出内存为止的整个过程。了解类的生命周期对于理解Java程序的运行机制以及性能优化非常重要。本文会深入探寻类的生命周期&#xff0c;让读者对此有深刻印象。 目录 ​…...

三分算法与DeepSeek辅助证明是单峰函数

前置 单峰函数有唯一的最大值&#xff0c;最大值左侧的数值严格单调递增&#xff0c;最大值右侧的数值严格单调递减。 单谷函数有唯一的最小值&#xff0c;最小值左侧的数值严格单调递减&#xff0c;最小值右侧的数值严格单调递增。 三分的本质 三分和二分一样都是通过不断缩…...