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

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

什么是有效的预测性维护 ?

在现代制造业的背景下&#xff0c;设备的可靠性和生产效率成为了企业追求的关键目标。而预测性维护&#xff08;Predictive Maintenance&#xff0c;简称PdM&#xff09;作为一种先进的维护策略&#xff0c;逐渐成为了实现这些目标的重要工具。然而&#xff0c;什么是有效的预测…

Windows wsl2支持systemd

背景 很多Linux发行版都是使用systemd来管理程序进程&#xff0c;但是在WSL中默认是用init来管理进程的。 为了符合长久的使用习惯&#xff0c;且省去不必要的学习成本&#xff0c;就在WSL的发行版&#xff08;我这里安装的是Ubuntu20.04&#xff09;中支持systemd&#xff0…

计算机视觉 -- 图像分割

文章目录 1. 图像分割2. FCN2.1 语义分割– FCN &#xff08;Fully Convolutional Networks&#xff09;2.2 FCN--deconv2.3 Unpool2.4 拓展–DeconvNet 3. 实例分割3.1 实例分割--Mask R-CNN3.2 Mask R-CNN3.3 Faster R-CNN与 Mask R-CNN3.4 Mask R-CNN&#xff1a;Resnet1013…

常用的Selenium基础使用模板和简单封装

前言 近来又用上了 Selneium &#xff0c;因为反复用到&#xff0c;所以在这里将一些常用的方法封装起来&#xff0c;方便后续的使用。 在这篇文章中&#xff0c;我们将探讨 Selenium 的基础模板和基础封装&#xff0c;以便更好地理解 Selenium 的使用方法。 在Selenium的使…

web---Vue2_语法学习

文章目录 1、Vue2 常用指令1.1 初始Vue1.2 Vue的两种模板语法1.3 数据绑定1.4 el和data的两种写法1.5 MVVM模型1.6 Vue中的数据代理1.7 事件处理--事件的基本使用1.7 事件处理--事件修饰符1.7 事件处理--键盘事件1.8 计算属性1.9 监视属性1.9 深度监视2.0 绑定css样式2.1 条件渲…

spring复习:(57)PropertyOverrideConfigurer用法及工作原理

一、属性配置文件 dataSource.urljdbc:mysql://xxx.xxx.xxx.xxx/test dataSource.usernameroot dataSource.passwordxxxxxx dataSource.driverClassNamecom.mysql.jdbc.Driver #dataSource.typecom.alibaba.druid.pool.DruidDataSource二、spring配置文件 <?xml version&…

NPM 管理组织成员

目录 1、向组织添加成员 1.1 邀请成员加入您的组织 1.2 撤销组织邀请 2、接收或拒接组织邀请 2.1 接收组织邀请 2.2 拒绝组织邀请 3、组织角色和权限 4、管理组织权限 5、从组织中删除成员 1、向组织添加成员 作为组织所有者&#xff0c;您可以将其他npm用户添加到…

[保研/考研机试] KY212 二叉树遍历 华中科技大学复试上机题 C++实现

题目链接&#xff1a; 二叉树遍历_牛客题霸_牛客网二叉树的前序、中序、后序遍历的定义&#xff1a; 前序遍历&#xff1a;对任一子树&#xff0c;先访问根&#xff0c;然后遍历其左子树&#xff0c;最。题目来自【牛客题霸】https://www.nowcoder.com/share/jump/43719512169…

【仿写tomcat】六、解析xml文件配置端口、线程池核心参数

线程池改造 上一篇文章中我们用了Excutors创建了线程&#xff0c;这里我们将它改造成包含所有线程池核心参数的形式。 package com.tomcatServer.http;import java.util.concurrent.*;/*** 线程池跑龙套** author ez4sterben* date 2023/08/05*/ public class ThreadPool {pr…

php 系列题目,包含查看后端源代码

一、弱类型比较问题 原则&#xff1a; 1.字符串和数字比较&#xff0c;字符串回被转换成数字。 "admin" 0&#xff08;true) admin被转换成数字&#xff0c;由于admin是字符串&#xff0c;转换失败&#xff0c;变成0 int(admin)0,所以比较结果是ture 2.混合字符串转…

RabbitMq的使用

最近处理访客记录所以&#xff0c;来学习下rabbitMQ。之前同事已经写好了&#xff0c;这里只需要进行消费&#xff0c;后续会逐渐完善。 0.介绍 0.1交换机&#xff08;Exchanges&#xff09; rabbitmq中生产者发送的消息都是发送到交换机&#xff0c;再由交换机推入队列。所…

百度云BOS云存储的图片如何在访问时,同时进行格式转换、缩放等处理

前言 之前做了一个图片格式转换和压缩的服务&#xff0c;结果太占内存。后来查到在访问图片链接时&#xff0c;支持进行图片压缩和格式转换&#xff0c;本来想着先格式转换、压缩图片再上传到BOS&#xff0c;现在变成了上传后&#xff0c;访问时进行压缩和格式转换。想了想&am…

无人机航管应答机 ping200XR

产品概述 ping200XR是一个完整的系统&#xff0c;旨在满足航管应答器和自动相关监视广播(ADS-B)的要求&#xff0c;在管制空域操作无人航空系统(UAS)。该系统完全可配置为模式A&#xff0c;模式C&#xff0c;模式S转发器和扩展ADS-B发射机的任何组合。ping200XR包括一个精度超…

AutoDev 1.1.3 登场,个性化 AI 辅助:私有化大模型、自主设计 prompt、定义独特规则...

在过去的半个月里&#xff0c;我们为开源辅助编程工具 AutoDev 添加了更强大的自定义能力&#xff0c;现在你可以&#xff1a; 使用自己部署的开源大模型自己配置 Intellij IDEA 中的行为自定义开发过程中的规范 当然了&#xff0c;如果您自身拥有开发能力的话&#xff0c;建议…

MinIO线上扩容实战

硬件投入肯定是随着业务的增长而增长&#xff0c;这就要求中间件平台必须提供水平伸缩机制&#xff0c;MinIO对象存储服务也不例外&#xff0c;本文就详细介绍MinIO的扩容。 Minio支持通过增加新的Server Pool来扩容老的集群。每个Server Pool都是一个相对独立的故障域&#x…

uniapp微信小程序点击右上角菜单分享功能权限配置

个人项目地址&#xff1a; SubTopH前端开发个人站 &#xff08;自己开发的前端功能和UI组件&#xff0c;一些有趣的小功能&#xff0c;感兴趣的伙伴可以访问&#xff0c;欢迎提出更好的想法&#xff0c;私信沟通&#xff0c;网站属于静态页面&#xff09; SubTopH前端开发个人站…

IPv4,IPv6,TCP,路由

主要回顾一下TCP&#xff0f;IP的传输过程&#xff0c;在这个过程中&#xff0c;做了什么事情 ip : 网际协议,IP协议能让世界上任意两台计算机之间进行通信。 IP协议的三大功能&#xff1a; 寻址和路由传递服务&#xff1a;不可靠&#xff08;尽最大努力交付传输数据包&…

Kali 分析和管理网络

查看网络 ifconfig 命令 ┌──(root㉿kali)-[~] # eth0:有线网卡 └─# ifconfig eth0: flags4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500inet 192.168.56.128 netmask 255.255.255.0 broadcast 192.168.56.255inet6 fe80::20c:29ff:feb3:7991 prefixlen 64 …

C++信息学奥赛1131:基因相关性

这段代码的功能是比较两个字符串的相似度&#xff0c;并根据给定的阈值判断是否相似。 解析注释后的代码如下&#xff1a; #include <iostream> #include <string> using namespace std;int main() {double bf; // 定义双精度浮点数变量bf&#xff0c;用于存储阈…

LED驱动型IC芯片的原理介绍

一、LED驱动器是什么 LED驱动器&#xff08;LED Driver&#xff09;&#xff0c;是指驱动LED发光或LED模块组件正常工作的电源调整电子器件。由于LED PN结的导通特性决定&#xff0c;它能适应的电源电压和电流变动范围十分狭窄&#xff0c;稍许偏离就可能无法点亮LED或者发光效…