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

什么是信号处理?如何处理信号?

C语言信号处理详解

第一部分:什么是信号?

信号是一种进程间通信的机制,用于通知进程发生了某种事件或异常情况。在C语言中,信号是一种软件中断,它可以被操作系统或其他进程发送给目标进程。每个信号都有一个唯一的数字标识符,称为信号编号(Signal Number)。例如,常见的信号包括SIGINT(中断进程)、SIGTERM(终止进程)、SIGSEGV(段错误)等。

信号可以用于以下几种情况:

  1. 进程间通信:一个进程可以向另一个进程发送信号,以通知它某个事件的发生或请求其执行某个操作。

  2. 异常处理:操作系统可以向进程发送信号,以通知它发生了某个异常情况,例如除零错误、段错误等。

  3. 用户交互:用户可以通过键盘或终端发送信号来与正在运行的程序交互,例如使用Ctrl+C发送SIGINT信号来中断程序的执行。

第二部分:信号的基本操作

2.1 发送信号

在C语言中,可以使用kill函数或raise函数来向目标进程发送信号。

#include <signal.h>int kill(pid_t pid, int sig);
int raise(int sig);
  • kill函数用于向指定的进程发送信号sigpid参数指定了目标进程的进程ID。如果pid为正数,则表示发送信号给进程ID为pid的进程;如果pid为0,则表示发送信号给当前进程所在进程组的所有进程;如果pid为-1,则表示发送信号给当前用户的所有进程;如果pid小于-1,则表示发送信号给进程组ID等于pid的所有进程。

  • raise函数用于向当前进程发送信号sig

2.2 接收信号

要在C程序中接收信号,可以使用signal函数或sigaction函数来注册信号处理函数。

2.2.1 signal函数

signal函数用于注册信号处理函数,其原型如下:

#include <signal.h>void (*signal(int sig, void (*handler)(int)))(int);
  • sig参数指定了要处理的信号,例如SIGINTSIGTERM等。
  • handler参数是一个函数指针,指向处理该信号的函数。

以下是一个使用signal函数注册信号处理函数的示例:

#include <stdio.h>
#include <signal.h>
#include <unistd.h>void sigint_handler(int signo) {printf("Received SIGINT signal (%d).\n", signo);
}int main() {// 注册SIGINT信号处理函数signal(SIGINT, sigint_handler);while (1) {sleep(1); // 模拟程序执行}return 0;
}

在上面的示例中,当程序接收到Ctrl+C信号(SIGINT)时,将调用sigint_handler函数来处理该信号。

2.2.2 sigaction函数

sigaction函数提供了更加灵活的信号处理方式,其原型如下:

#include <signal.h>int sigaction(int sig, const struct sigaction *restrict act, struct sigaction *restrict oldact);
  • sig参数指定了要处理的信号,例如SIGINTSIGTERM等。
  • act参数是一个指向struct sigaction结构的指针,用于设置信号处理的行为。
  • oldact参数是一个指向struct sigaction结构的指针,用于获取之前的信号处理行为。

struct sigaction结构定义如下:

struct sigaction {void (*sa_handler)(int); // 信号处理函数sigset_t sa_mask;        // 信号屏蔽字集合int sa_flags;            // 信号处理标志void (*sa_sigaction)(int, siginfo_t *, void *); // 信号处理函数(扩展)
};

以下是一个使用sigaction函数注册信号处理函数的示例:

#include <stdio.h>
#include <signal.h>
#include <unistd.h>void sigint_handler(int signo) {printf("Received SIGINT signal (%d).\n", signo);
}int main() {struct sigaction sa;sa.sa_handler = sigint_handler;sa.sa_flags = 0;sigemptyset(&sa.sa_mask);// 注册SIGINT信号处理函数sigaction(SIGINT, &sa, NULL);while (1) {sleep(1); // 模拟程序执行}return 0;
}

sigaction函数允许更灵活地控制信号处理,可以设置额外的标志和信号屏蔽。

2.3 信号默认操作

每个信号都有一个默认操作,例如终止进程、中断进程等。可以使用signal函数的第二个参数来指定信号处理函数,或者将信号处理函数设置为SIG_IGN(忽略信号)或SIG_DFL(恢复默认操作)。

以下是一些常见的信号默认操作:

  • SIGINT(Ctrl+C)默认操作是中断进程。
  • SIGTERM默认操作是终止进程。
  • SIGQUIT(Ctrl+\)默认操作是终止进程并生成核心转储文件。
  • SIGHUP默认操作是终止进程,通常用于重新加载配置。
  • SIGKILL默认操作是强制终止进程,无法被捕获或忽略。

第三部分:信号处理函数

信号处理函数是用户自定义的函数,用于处理特定信号的发生。信号处理函数的原型通常是:

void handler_function(int signo);
  • signo参数指定了触发信号处理函数的信号编号。

信号处理函数可以执行各种操作,例如记录日志、清理资源、继续执行等。然而,由于信号处理函数在信号发生时异步执行,因此需要谨慎编写,避免使用不可重入函数、全局变量等可能导致不确定行为的操作。

以下是一个示例,演示如何编写一个简单的信号处理函数:

#include <stdio.h>
#include <signal.h>
#include <unistd.h>void sigint_handler(int signo) {printf("Received SIGINT signal (%d).\n", signo);
}int main() {// 注册SIGINT信号处理函数signal(SIGINT, sigint_handler);while (1) {sleep(1); // 模拟程序执行}return 0;
}

在上面的示例中,sigint_handler函数用于处理SIGINT信号的发生,它简单地打印一条消息。

第四部分:信号的处理方式

信号的处理方式分为以下几种:

4.1 忽略信号

可以通过将信号处理函数设置为SIG_IGN来忽略信号。例如,要忽略SIGINT信号,可以这样做:

#include <signal.h>int main() {signal(SIGINT, SIG_IGN); // 忽略SIGINT信号while (1) {// 程序不会响应Ctrl+C}return 0;
}

4.2 捕获信号

通过注册信号处理函数,可以捕获信号并在发生时执行特定操作。示例如前面所示。

4.3 恢复默认操作

可以将信号处理函数设置为SIG_DFL,以恢复信号的默认操作。例如,要恢复SIGINT信号的默认操作,可以这样做:

#include <signal.h>int main() {signal(SIGINT, SIG_DFL); // 恢复SIGINT信号的默认操作while (1) {// Ctrl+C将中断进程}return 0;
}

4.4 阻塞信号

可以使用sigprocmask函数来阻塞或解除阻塞信号。阻塞信号意味着信号将被排队,不会立即传递给进程。当信号解除阻塞时,排队的信号将被传递给进程。

        

#include <stdio.h>
#include <signal.h>
#include <unistd.h>void sigint_handler(int signo) {printf("Received SIGINT signal (%d).\n", signo);
}int main() {sigset_t mask;sigemptyset(&mask);sigaddset(&mask, SIGINT);// 阻塞SIGINT信号sigprocmask(SIG_BLOCK, &mask, NULL);// 注册SIGINT信号处理函数signal(SIGINT, sigint_handler);while (1) {sleep(1);printf("Working...\n");}return 0;
}

在上面的示例中,sigprocmask函数用于阻塞SIGINT信号,直到解除阻塞时才会执行信号处理函数。

4.5 发送信号

前面已经介绍了如何使用kill函数或raise函数来向进程发送信号。

第五部分:信号处理的注意事项

5.1 信号不可靠性

信号处理是一种异步操作,因此存在信号不可靠性的问题。例如,如果在两次信号之间处理函数没有完成,第二个信号可能会丢失。因此,在信号处理函数中应谨慎使用全局变量、不可重入函数等。

5.2 信号重入

信号处理函数应该是可重入的,即可以在信号处理函数执行期间再次接收到相同信号而不会导致问题。要实现可重入性,可以使用sigaction函数注册信号处理函数,同时在信号处理函数中避免使用全局变量和不可重入函数。

5.3 信号与系统调用

在系统调用期间,通常会将信号屏蔽(阻塞),以避免在关键操作期间接收到信号导致不一致性。一些系统调用会自动恢复信号屏蔽,但一些不会。因此,在系统调用中要注意信号处理的状态。

5.4 信号与多线程

多线程程序中,每个线程都有自己的信号屏蔽状态。默认情况下,新线程会继承创建它的线程的信号屏蔽状态。因此,在多线程程序中要小心管理信号屏蔽状态,以确保线程间的信号不会相互干扰。

第六部分:总结

信号处理是C语言中处理异步事件和异常情况的重要机制。本文介绍了信号的基本概念、信号的发送和接收、信号处理函数的编写方式、信号的处理方式以及注意事项。了解信号处理可以帮助程序员更好地处理各种情况下的信号,提高程序的健壮性和可靠性。在实际编程中,要谨慎处理信号,避免不可预测的行为,保证程序的稳定性。

相关文章:

什么是信号处理?如何处理信号?

C语言信号处理详解 第一部分&#xff1a;什么是信号&#xff1f; 信号是一种进程间通信的机制&#xff0c;用于通知进程发生了某种事件或异常情况。在C语言中&#xff0c;信号是一种软件中断&#xff0c;它可以被操作系统或其他进程发送给目标进程。每个信号都有一个唯一的数…...

谈谈 Redis 数据类型底层的数据结构?

谈谈 Redis 数据类型底层的数据结构? RedisObject 在 Redis 中&#xff0c;redisObject 是一个非常重要的数据结构&#xff0c;它用于保存字符串、列表、集合、哈希表和有序集合等类型的值。以下是关于 redisObject 结构体的定义&#xff1a; typedef struct redisObject {…...

九、GC收集日志

JVM由浅入深系列一、关于Java性能的误解二、Java性能概述三、了解JVM概述四、探索JVM架构五、垃圾收集基础六、HotSpot中的垃圾收集七、垃圾收集中级八、垃圾收集高级👋GC收集日志 ⚽️1. 认识GC收集日志 垃圾收集日志是一个重要的信息来源,对于与性能相关的一些悬而未决的…...

SimpleCG动画示例--汉诺塔动画演示

前言 SimpleCG的使用方法在前面已经介绍了许多&#xff0c;有兴趣的同学如果有去动手&#xff0c;制作一些简单动画应该没多大问题的。所以这次我们来演示一下简单动画。我们刚学习C语言的递归函数时&#xff0c;有一个经典例子相信很多同学都写过&#xff0c;那就是汉诺塔。那…...

反弹shell脚本(php-reverse-shell)

平时经常打靶机 这里贴一个 反弹shell的脚本 <?php // php-reverse-shell - A Reverse Shell implementation in PHP // Copyright (C) 2007 pentestmonkeypentestmonkey.net // // This tool may be used for legal purposes only. Users take full responsibility // f…...

XSS-labs

XSS常见的触发标签_xss标签_H3rmesk1t的博客-CSDN博客 该补习补习xss漏洞了 漏洞原理 网站存在 静态 和 动态 网站 xss 针对的网站 就是 动态网站 动态网站会根据 用户的环境 与 需求 反馈出 不同的响应静态页面 代码写死了 只会存在代码中有的内容 通过动态网站 用户体…...

C++简单实现AVL树

目录 一、AVL树的概念 二、AVL树的性质 三、AVL树节点的定义 四、AVL树的插入 4.1 parent的平衡因子为0 4.2 parent的平衡因子为1或-1 4.3 parent的平衡因子为2或-2 4.3.1 左单旋 4.3.2 右单旋 4.3.3 先左单旋再右单旋 4.3.4 先右单旋再左单旋 4.4 插入节点完整代码…...

UE4 Cesium 与ultra dynamic sky插件天气融合

晴天&#xff1a; 雨天&#xff1a; 雨天湿度&#xff1a; 小雪&#xff1a; 中雪&#xff1a; 找到该路径这个材质&#xff1a; 双击点开&#xff1a; 将Wet_Weather_Effects与Snow_Weather_Effects复制下来&#xff0c;包括参数节点 找到该路径这个材质&#xff0c;双击点开&…...

SpringCloud Gateway--Predicate/断言(详细介绍)下

&#x1f600;前言 本篇博文是关于SpringCloud Gateway–Predicate/断言&#xff08;详细介绍&#xff09;下&#xff0c;希望你能够喜欢 &#x1f3e0;个人主页&#xff1a;晨犀主页 &#x1f9d1;个人简介&#xff1a;大家好&#xff0c;我是晨犀&#xff0c;希望我的文章可以…...

SOC芯片学习--GPIO简介

原创 硬件设计技术 硬件设计技术 2023-07-20 00:04 发表于广东 收录于合集#集成电路--IC7个 一、GPIO定义、分类&#xff1a; GPIO&#xff08;英语&#xff1a;General-purpose input/output&#xff09;&#xff0c;通用型之输入输出的简称&#xff0c;其接脚可以供使用者由…...

skywalking源码本地编译运行经验总结

前言 最近工作原因在弄skywalking&#xff0c;为了进一步熟悉拉了代码下来准备debug&#xff0c;但是编译启动项目我就费了老大劲了&#xff0c;所以准备写这篇&#xff0c;帮兄弟们少踩点坑。 正确步骤 既然是用开源的东西&#xff0c;那么最好就是按照人家的方式使用&…...

K8s架构简述

以部署一个nginx服务说明kubernetes系统各个组件调用关系&#xff1a; 一旦kubernetes环境启动之后&#xff0c;master和node都会将自身的信息存储到etcd数据库中 一个nginx服务的安装请求会首先被发送到master节点的apiServer组件 apiServer组件会调用scheduler组件来决定到底…...

linkedlist和arraylist的区别

LinkedList和ArrayList都是常见的数据结构&#xff0c;用于存储和操作集合元素&#xff0c;如果需要频繁进行插入和删除操作&#xff0c;LinkedList可能更适合。如果需要快速随机访问和较小的内存占用&#xff0c;ArrayList可能更合适。 以下是它们之间存在一些关键的区别&…...

[尚硅谷React笔记]——第2章 React面向组件编程

目录&#xff1a; 基本理解和使用&#xff1a; 使用React开发者工具调试函数式组件复习类的基本知识类式组件组件三大核心属性1: state 复习类中方法this指向&#xff1a; 复习bind函数&#xff1a;解决changeWeather中this指向问题&#xff1a;一般写法&#xff1a;state.htm…...

嵌入式学习笔记(40)看门狗定时器

7.5.1什么是看门狗、有何用 (1)看门狗定时器和普通定时器并无本质区别。定时器可以设定一个时间&#xff0c;在这个时间完成之前定时器不断计时&#xff0c;时间到的时候定时器会复位CPU&#xff08;重启系统&#xff09;。 (2)系统正常工作的时候当然不希望被重启&#xff0…...

点击、拖拉拽,BI系统让业务掌握数据分析主动权

在今天的商业环境中&#xff0c;数据分析已经成为企业获取竞争优势的关键因素之一。然而&#xff0c;许多企业在面对复杂的数据分析工具时&#xff0c;却常常感到困扰。这些工具往往需要专业的技术人员操作&#xff0c;而且界面复杂&#xff0c;难以理解和使用。对业务人员来说…...

C++模拟题[第一周-T1] 扑克

[第一周-T1] 扑克 题目描述 斗地主是一种使用 A \tt A A 到 K \tt K K 加上大小王的共 54 54 54 张扑克牌来进行的游戏&#xff0c;其中大小王各一张&#xff0c;其它数码牌各四张。在斗地主中&#xff0c;牌的大小关系根据牌的数码表示如下&#xff1a; 3 < 4 < 5 …...

ciscn_2019_s_9

ciscn_2019_s_9 Arch: i386-32-little RELRO: Partial RELRO Stack: No canary found NX: NX disabled PIE: No PIE (0x8048000) RWX: Has RWX segments32位&#xff0c;啥也没开&#xff0c;开心愉悦写shellcode int pwn() {char s[24]; // [esp8…...

微信、支付宝、百度、抖音开放平台第三方代小程序开发总结

大家好&#xff0c;我是小悟 小伙伴们都开启小长假了吧&#xff0c;值此中秋国庆双节之际&#xff0c;小悟祝所有的小伙伴们节日快乐。 支付宝社区很用心&#xff0c;还特意给寄了袋月饼&#xff0c;愿中秋节的圆月带给你身体健康&#xff0c;幸福团圆&#xff0c;国庆节的旗帜…...

C语言协程

协程&#xff08;Coroutine&#xff09;是一种程序运行方式&#xff0c;相比于线程和进程&#xff0c;协程更加轻量级&#xff0c;可以被视为一种用户态的线程&#xff0c;不需要内核的参与。 协程的特点在于其执行过程中可以被挂起&#xff08;Suspend&#xff09;&#xff0…...

RK3588安装python3.11(ubuntu18.04)

1.前言 看到rknn_toolkit_lite2更新了python3.11的安装包&#xff0c;马上更新一下 2.RK3588安装python3.11 Ubuntu上编译Python 3.11&#xff0c;您可以按照以下步骤进行操作&#xff1a; (1) 准备编译环境 在开始之前&#xff0c;确保您的系统已安装必要的编译工具和依赖项…...

‘Could not find first log file name in binary log index file‘的解决办法

mysql主从报异常Got fatal error 1236 from master when reading data from binary log: Could not find first log file name in binary log index file 数据库主从出错: Slave_IO_Running: No 一方面原因是因为网络通信的问题也有可能是日志读取错误的问题。以下是日志出错…...

快速排序与冒泡排序以及代码

快速排序 快速排序&#xff08;Quicksort&#xff09;是一种常用的排序算法&#xff0c;它基于分治的思想。 时间复杂度&#xff1a;O&#xff08;nlogn&#xff09; 空间复杂度&#xff1a;O&#xff08;logn&#xff09; 快速排序的基本思想如下&#xff1a; 选择一个元素…...

[React] 性能优化相关 (一)

文章目录 1.React.memo2.useMemo3.useCallback4.useTransition5.useDeferredValue 1.React.memo 当父组件被重新渲染的时候&#xff0c;也会触发子组件的重新渲染&#xff0c;这样就多出了无意义的性能开销。如果子组件的状态没有发生变化&#xff0c;则子组件是不需要被重新渲…...

云中网络的隔离GREVXLAN

底层的物理网络设备组成的网络我们称为 Underlay 网络&#xff0c;而用于虚拟机和云中的这些技术组成的网络称为 Overlay 网络&#xff0c;这是一种基于物理网络的虚拟化网络实现。 第一个技术是 GRE&#xff0c;全称 Generic Routing Encapsulation&#xff0c;它是一种 IP-o…...

【【萌新的RiscV学习之流水线控制-9】】

萌新的RiscV学习之流水线控制-9 我们按照在之前的单周期设计加入控制单元 那么我们能够在后续的设计中提供方便 我们也在流水线中加入一个control单元 我们先按照书上的指令op码值介绍一遍基本功能 接下来我们讲述control 的 控制效果 关于这些串口判别的使用 由于控制线从…...

MySQL 通过存储过程高效插入100w条数据

目录 一、前言二、创建表三、编写存储过程插入数据四、高效插入数据方案4.1、插入数据时删除表中全部索引4.2、存储过程中使用统一事务插入&#xff08;性能显著提升&#xff09;4.3、调整MySQL系统配置&#xff08;性能显著提升&#xff0c;适合存储过程没有使用统一事务&…...

国庆10.1

用select实现服务器并发 ser #include <myhead.h> #define ERR_MSG(msg) do{\fprintf(stderr, "__%d__", __LINE__);\perror(msg);\ }while(0)#define PORT 8888 //端口号&#xff0c;范围1024~49151 #define IP "192.168.1.205" //本机…...

[C++_containers]10分钟让你掌握vector

前言 在一个容器的创建或是使用之前&#xff0c;我们应该先明白这个容器的一些特征。 我们可以通过文档来来了解&#xff0c;当然我也会将重要的部分写在下面。 1. vector 是表示可变大小数组的序列容器。 2. 就像数组一样&#xff0c; vector 也采用的连续存储空间来存储元…...

前端与后端:程序中两个不同的领域

前端和后端是构成一个完整的计算机应用系统的两个主要部分。它们分别负责不同的功能和任务&#xff0c;有以下几个方面的区别&#xff1a; 功能&#xff1a;前端主要负责用户界面的呈现和交互&#xff0c;包括网页的设计、布局、样式、动画效果和用户输入等。后端则处理网站或应…...

百度提交网站已删内容/安卓嗅探app视频真实地址

​在我们学习数据科学的时候&#xff0c;通常数据都存在csv等格式的文件中&#xff0c;但是事实上在企业里&#xff0c;数据往往被存储到数据库中。今天我将介绍如何使用Jupyter Notebooks或JupyterLab作为SQL IDE。设置首先&#xff0c;我们需要安装一个库以确保可以直接在Not…...

网站防盗链怎么做/seo搜索引擎优化技术

每日github继续更新&#xff1a;21&#xff0c;tensorflow / modelstensorflow已经训练好的一些模型。学习tensorflow从这里开始。22&#xff0c;electron / electron 如果你可以建一个网站&#xff0c;你就可以建一个桌面应用程序。 Electron 是一个使用 JavaScript, HTML 和 …...

外贸网站源码php/上海广告公司

在周三一位安全分析师曾提出&#xff0c;三星子公司LoopPay的安全漏洞可能产生更坏的影响。与其说是普通的手机用户数据泄露&#xff0c;还不如称其为有关部门试图实施的监控行动。 LoopPay攻击事件的本质 三星承认了LoopPay的攻击事件。他们在二月份收购了该子公司&#xff0c…...

企业网站空间备案吗/海南seo代理加盟供应商

一、适配背景 1、Android 4.4及以上设备 Android 4.4&#xff08;简称 4.4&#xff09;及以上设备 的图片文件路径与4.4以下设备的路径是完全不一样的&#xff0c;需要开发者自行拼接。 2、Android 6.0 及以上设备 Android 6.0&#xff08;简称 6.0 &#xff09;及以上设备 在…...

腾讯云可以用wordpress教程/seo外链资源

目的&#xff1a;掌握 堆排序 的 基本思想与过程、代码实现、时间复杂度 1、基本思想与过程&#xff1a; &#xff08;1&#xff09;将数组看做是一棵二叉树&#xff0c;并且是完全二叉树&#xff0c;将其变为最大二叉堆&#xff0c;即每一个父节点均大于其相连的子节点&#x…...

招聘网站建设/b站网站推广mmm

我的上网本只有1024x768的分辨率&#xff0c;运行文华6要求更高分辨率显示器。 通过对显示器安装驱动&#xff0c;获得虚拟的高分辨率支持。 1、打开显示器的属性&#xff0c;选择&#xff1a;设置->高级->监视器&#xff1b;2、这里我们可以看到监视器类型是默认的”即插…...