Unix信号处理

信号的基本概念我已经在上一节中简单介绍了,大家可以去看我的上一篇博客:

Unix中的进程和线程-2-CSDN博客

1.信号的产生

kill函数:

#include <signal.h>
#include <fcntl.h>
#include<t_stdio.h>
//自定义信号处理函数,n为信号编号
void handle(int n){printf("this is a test..\n");return;}int main(void){//从父进程继承信号处理函数//采用默认处理方式signal(2,SIG_IGN);//改变2号进程的处理函数,忽略2号信号signal(3,handle);//对3号信号使用自定义处理函数pid_t pid = fork();if(pid==-1)E_MSG("fork",-1);while(1);return 0;
}

  1. signal(2,SIG_IGN):使用signal()函数,将2号信号(通常是SIGINT,即Ctrl+C)的处理方式设置为忽略(SIG_IGN)。这意味着当程序接收到Ctrl+C时,不会终止程序,而是忽略该信号。
  2. signal(3,handle):将3号信号的处理方式设置为调用自定义的信号处理函数handle。这表示当程序接收到3号信号时(例如Ctrl+\),会执行handle函数中定义的操作。
  3. pid_t pid = fork();:创建一个子进程。
  4. if(pid==-1)E_MSG("fork",-1);:如果fork()调用失败,输出错误消息并退出程序。
  5. while(1);:在这个循环中,父进程和子进程都会进入一个无限循环,使得程序一直处于运行状态。

这个程序主要演示了信号处理的基本用法,以及父子进程之间对信号处理函数的继承。通过signal()函数可以设置特定信号的处理方式,可以是忽略该信号、采用默认的处理方式,或者调用自定义的信号处理函数。

 kill函数的仿写:

#include<t_stdio.h>
#include<t_file.h>
#include <sys/types.h>
#include <signal.h>int main(int argc , char * argv[]){//将命令行的参数转化为整数类型kill (atoi(argv[2]),atoi(argv[1]));return 0;
}

 alarm函数:

alarm函数是一个用于在指定时间后发送信号的函数。它允许你在程序中设置一个定时器,当定时器计时时间到达后,系统会向当前进程发送一个 SIGALRM 信号。这通常用于实现超时控制或者周期性任务。

以下是 alarm 函数的声明:

#include <unistd.h>unsigned int alarm(unsigned int seconds);

alarm 函数接受一个 unsigned int 类型的参数 seconds,表示定时器的计时时间,单位是秒。当调用 alarm 函数后,系统会在指定的秒数之后向当前进程发送 SIGALRM 信号。

如果之前已经设置过定时器,调用 alarm 函数会取消之前的定时器,并设置新的定时器。如果 seconds 参数为 0,则之前设置的定时器会被取消,且不会设置新的定时器。

下面是一个简单的示例代码,演示了如何使用 alarm 函数实现一个定时器:

#include <stdio.h>
#include <unistd.h>
#include <signal.h>void handler(int signum) {printf("Received SIGALRM signal.\n");// 处理定时器触发后的逻辑
}int main() {// 注册信号处理函数signal(SIGALRM, handler);printf("Setting up alarm for 5 seconds.\n");// 设置定时器为 5 秒alarm(5);// 进入一个无限循环while (1) {// 这里可以执行一些其他任务// 例如:等待用户输入等}return 0;
}

在这个示例中,首先注册了一个信号处理函数 handler,用于处理 SIGALRM 信号。然后调用 alarm(5) 设置了一个定时器,时间为 5 秒。当定时器计时时间到达时,系统会发送 SIGALRM 信号,进而触发信号处理函数 handler,在该处理函数中打印了一条消息。

  2.信号的暂停

如下:

#include<stdio.h>
#include <unistd.h>
#include<signal.h>
//信号处理函数
void handle(int n){}unsigned int t_sleeps(unsigned int seconds){alarm(2);//设置一个两秒闹钟pause();//停止进程return alarm(0);//取消原来的脑子,返回未决时间}int main(void){//不能忽略SIGALRM信号,这样pause会一直起作用,不会停止//signal(SIGALRM,SIG_IGN);signal(SIGALRM,handle);while(1){t_sleeps(2);printf("nihao...\n");}return 0;
}

  1. #include<stdio.h>:包含了标准输入输出的头文件。
  2. #include <unistd.h>:包含了UNIX标准的头文件,其中包括了alarm()pause()函数的声明。
  3. #include<signal.h>:包含了信号处理相关的头文件。
  4. void handle(int n){}:定义了一个空的信号处理函数handle(),用于处理信号。在这个示例中,它并没有实际功能。
  5. unsigned int t_sleeps(unsigned int seconds):定义了一个自定义的睡眠函数t_sleeps(),它接受一个参数seconds,表示睡眠的秒数,并返回一个unsigned int类型的值,表示剩余的未决定时间。
  6. alarm(2);:调用alarm()函数,设置一个两秒的定时器。这会在两秒后向进程发送一个SIGALRM信号。
  7. pause();:调用pause()函数,使进程暂停,等待信号的到来。当接收到信号后,进程会恢复执行。
  8. return alarm(0);:取消之前设置的闹钟,并返回未决定的时间。

main()函数中:

  • 注册了信号处理函数,将SIGALRM信号的处理方式设置为handle函数。这一步通常是为了确保程序在接收到SIGALRM信号时不会终止。
  • 使用一个无限循环,调用t_sleeps(2)函数,表示每隔两秒打印一次"nihao..."。

这个程序的主要目的是演示如何使用alarm()pause()函数实现一个自定义的睡眠函数。当调用t_sleeps()函数时,程序会暂停执行两秒钟,然后继续执行后续的代码。

 3.信号阻塞和信号集

 3.1信号集的常用操作:

#include<signal.h>
#include<t_stdio.h>int main(void){//定义信号集类型变量set__sigset_t set;//初始化setsigemptyset(&set);//将2号信号添加到信号集set中sigaddset(&set,2);sigaddset(&set,3);//测试3号信号是不是信号集中的一员int is=sigismember(&set,3);if(is==-1)E_MSG("sigismember",-1);if(is) printf("signum is member of set..\n");else printf("signum is not member of set..\n");//将3号信号从信号集中移除sigdelset(&set , 3);is=sigismember(&set,3);if(is==-1)E_MSG("sigismember",-1);if(is) printf("del signum is member of set..\n");else printf("del signum is not member of set..\n");return 0;
}

 信号的阻塞:

3.2进程的信号掩码集:

#include<t_stdio.h>
#include <asm-generic/signal-defs.h>
#include <bits/sigset.h>int main(void){//定义信号集的变量set__sigset_t set;//初始化setsigemptyset(&set);//将2,3,9号信号添加到信号集set中sigaddset(&set,2);sigaddset(&set,3);sigaddset(&set,9);//将set设置为进程的信号掩码集int sm=sigprocmask(SIG_SETMASK,&set,NULL);if(sm==-1)E_MSG("sigprocmask",-1);while(1){}return 0;
}
  1. __sigset_t set;:定义了一个变量 set,类型为 __sigset_t,这是一个用于表示信号集的数据结构。
  2. sigemptyset(&set);:使用 sigemptyset() 函数将信号集 set 清空,确保其中不包含任何信号。
  3. sigaddset(&set,2);sigaddset(&set,3); 和 sigaddset(&set,9);:使用 sigaddset() 函数向信号集 set 中添加信号。在这里,将信号2、3和9添加到 set 中,分别代表 SIGINTSIGQUIT 和 SIGKILL 信号。
  4. int sm=sigprocmask(SIG_SETMASK,&set,NULL);:使用 sigprocmask() 函数将 set 中的信号设置为进程的信号掩码集。SIG_SETMASK 表示设置当前信号掩码为 set 中包含的信号集合,即阻塞信号2、3和9。如果设置成功,sigprocmask() 返回0;否则返回-1,并且相应的错误信息会被设置到 errno 中。
  5. while(1){}:进入一个无限循环,使得程序一直处于运行状态,以保持信号掩码的设置。

3.3未决信号集:

#include<t_stdio.h>
#include<signal.h>
#include <asm-generic/signal-defs.h>
#include<unistd.h>int main(void){//定义信号集类型变量__sigset_t set , pset;//初始化信号集sigemptyset(&set);//添加信号到setsigaddset(&set,2);//将set设置为进程的信号掩码集int sm =sigprocmask(SIG_BLOCK,&set,NULL);if(sm==-1)E_MSG("sigismember",-1);while(1){sleep(1);//获取进程的未决信号集,pset存放的就是进程的未决信号集sigpending(&pset);int is=sigismember(&pset,2);if(is==-1)E_MSG("sigismemeber",-1);is? printf("yes..\n") : printf("no..\n");}return 0;
}
  1. 信号掩码集(signal mask): 信号掩码集是用于阻塞一组信号的,也就是说,被加入到该进程的信号掩码集中的信号,都会被阻塞,直到被从掩码集中移除。在你的代码中,通过sigprocmask(SIG_BLOCK,&set,NULL);将2号信号(SIGINT,即Ctrl+C触发的中断信号)加入到了掩码集中,从而阻塞了该信号。
  2. 未决信号集(pending signal): 未决信号集是指当前被阻塞,并且尚未处理的信号集合。只要这个信号在掩码集中,那么该信号一旦产生,就会被追加到未决信号集中,等待处理。在代码中,未决信号集的状态被周期性检查,并且每秒输出一次结果,显示2号信号是否存在于未决信号集中。 应用场景: 信号掩码集主要用于在处理某个信号时临时屏蔽其它会对当前处理过程产生干扰的信号,比如在处理某些复杂的业务逻辑或者关键数据更新时,防止被其它信号打断。 未决信号集则帮助我们得知哪些信号被阻塞且尚未得到处理,这对于调试程序,以及编写稳健的并发处理代码很有帮助。 

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

第十一届蓝桥杯物联网试题(省赛)

对于通信方面&#xff0c;还是终端A、B都保持接收状态&#xff0c;当要发送的数组不为空再发送数据&#xff0c;发送完后立即清除&#xff0c;接收数据的数组不为空则处理&#xff0c;处理完后立即清除&#xff0c;分工明确 继电器不亮一般可能是电压不够 将数据加空格再加\r…

线段树练习

1.单点修改区间查询 P3374 【模板】树状数组 1 题目描述 如题&#xff0c;已知一个数列&#xff0c;你需要进行下面两种操作&#xff1a; 将某一个数加上 x 求出某区间每一个数的和 输入格式 第一行包含两个正整数 n,m&#xff0c;分别表示该数列数字的个数和操作的总个…

C++之函数提高(HM)

目录 1.函数默认参数&#xff08;缺省参数&#xff09; 2.占位参数 3.函数重载 4.类和对象--封装 &#xff08;1&#xff09;圆类&#xff1a; &#xff08;2&#xff09;访问权限 &#xff08;3&#xff09;struct&&class &#xff08;4&#xff09;立方体类的…

C++利用键值对计算某一个数对应的最值及其索引位置

目录 一、算法概述二、代码实现1、计算最值2、计算最值及其索引 三、结果展示 本文由CSDN点云侠原创&#xff0c;原文链接。如果你不是在点云侠的博客中看到该文章&#xff0c;那么此处便是不要脸的爬虫与GPT。 一、算法概述 类似下图所示&#xff0c;计算第一列中1或2对应的最…

C#学生信息管理系统

一、引言 学生信息管理系统是现代学校管理的重要组成部分&#xff0c;它能够有效地管理学生的基本信息、课程信息、成绩信息等&#xff0c;提高学校管理的效率和质量。本文将介绍如何使用SQL Server数据库和C#语言在.NET平台上开发一个学生信息管理系统的课程设计项目。 二、项…

单细胞RNA测序(scRNA-seq)SRA数据下载及fastq-dumq数据拆分

单细胞RNA测序&#xff08;scRNA-seq&#xff09;入门可查看以下文章&#xff1a; 单细胞RNA测序&#xff08;scRNA-seq&#xff09;工作流程入门 单细胞RNA测序&#xff08;scRNA-seq&#xff09;细胞分离与扩增 1. NCBI查询scRNA-seq SRA数据 NCBI地址&#xff1a; https…

C++之类

目录 一&#xff1a;面向过程和面向对象的初步认识 二&#xff1a;类的引入 三&#xff1a;类的定义 3.1类的两种定义方式&#xff1a; 3.2成员变量命名的建议 四&#xff1a;类的访问限定符及封装 4.1类的访问限定符 4.2封装 一&#xff1a;面向过程和面向对象的初步认…

C#项目引用解决方案中其他项目dll时,出现黄色感叹号的解决方案

问题引入 今天拿着老师傅的老项目&#xff0c;需要做通讯调试&#xff0c;说测试一下&#xff0c;便添加了一个项目A来编写结构体&#xff0c;然后在窗体程序项目B中引用A&#xff0c;发现B一引用A&#xff0c;在B项目的引用下面A就多了个黄色感叹号&#xff0c;一编译B项目&am…

基于k8s的高性能综合web服务器搭建

目录 基于k8s的高性能综合web服务器搭建 项目描述&#xff1a; 项目规划图&#xff1a; 项目环境&#xff1a; k8s&#xff0c; docker centos7.9 nginx prometheus grafana flask ansible Jenkins等 1.规划设计整个集群的架构&#xff0c;k8s单master的集群环境&…

PyTorch深度学习——张量及其运算

深度学习框架的张量 张量的运算是深度学习的核心&#xff0c;如一张图片可以看作是四维的张量&#xff0c;一个迷你批次的文本可以看作是二维张量&#xff0c;基本上所有的深度学习模型都可以表示为张量的操作&#xff0c;梯度、反向传播算法也可以表示为张量和张量的运算 张…

scoped原理及使用

一、什么是scoped&#xff0c;为什么要用 在vue文件中的style标签上&#xff0c;有一个特殊的属性&#xff1a;scoped。 当一个style标签拥有scoped属性时&#xff0c;它的CSS样式就只能作用于当前的组件&#xff0c;通过该属性&#xff0c;可以使得组件之间的样式不互相污染。…

LLM大模型可视化-以nano-gpt为例

内容整理自&#xff1a;LLM 可视化 --- LLM Visualization (bbycroft.net)https://bbycroft.net/llm Introduction 介绍 Welcome to the walkthrough of the GPT large language model! Here well explore the model nano-gpt, with a mere 85,000 parameters. 欢迎来到 GPT 大…

深入浅出 -- 系统架构之分布式CAP理论和BASE理论

科技进步离不开理论支撑&#xff0c;而当下大行其道的分布式架构&#xff0c;透过繁荣昌盛表象&#xff0c;底层同样离不开诸多分布式理论撑持。当然&#xff0c;相信诸位在学习分布式相关技术时&#xff0c;必然学到过两个分布式领域中的基础理论&#xff0c;即&#xff1a;CA…

9.set容器的使用

文章目录 set容器1.构造和赋值代码工程运行结果 2.大小和交换代码工程运行结果 4.插入和删除代码工程运行结果 5.查找和统计工程代码运行结果 6.multset代码工程运行结果 7.指定排序规则代码工程运行结果 8.自定义数据类型排序代码工程运行结果 set容器 所有元素都会在插入时&a…

理解Three.js的相机

大家都知道我们生活中的相机&#xff0c;可以留下美好瞬间。那Three.js的相机是什么呢&#xff1f;Three.js创建的场景是三维的&#xff0c;而我们使用的显示器显然是二维的&#xff0c;相机就是抽象的定义了三维空间到二维显示器的投影方式。Three.js常见的相机有两类&#xf…

Stable diffusion 加载扩展列表报错解决方法

项目场景&#xff1a; 在使用Stable diffusion webui时&#xff0c;使用扩展列表出现错误 问题描述 点击loadfrom后&#xff0c;出现加载扩展列表报错 原因分析&#xff1a; 下载的扩展的时候&#xff0c;都是github 的url&#xff0c;需要科学上网&#xff0c;如果不能科学…

C语言动态内存空间分配

1. 前言 在讲内存分配前&#xff0c;咱来聊一下为什么会有内存分配这个概念呢&#xff0c;大家都知道C语言当中是有着许多的数据类型&#xff0c;使用这些数据类型就会在内存上开辟其相对应的空间&#xff0c;那既然会开辟相应的空间&#xff0c;为什么还会有内存分配呢&#x…

如何利用FLUENT计算流体力学方法解决大气与环境领域流动问题

ANSYS FLUENT是目前全球领先的商用CFD 软件&#xff0c;市场占有率达70%左右&#xff0c;是工程师和研究者不可多得的有力工具。由于采用了多种求解方法和多重网格加速收敛技术&#xff0c;因而FLUENT能达到最佳的收敛速度和求解精度。灵活的非结构化网格和基于解的自适应网格技…

Pycharm安装request的时候出现警告“由于目标计算机积极拒绝,无法连接”,然后出现报错无法安装

Pycharm安装request的时候出现警告“由于目标计算机积极拒绝&#xff0c;无法连接”&#xff0c;然后出现报错无法安装 一、报错二、解决办法 一、报错 二、解决办法 1、点击WinR 2、输入 regedit、进入注册表 3、在搜索框处输入&#xff1a;HKEY_CURRENT_USER\Software\Mic…

HTML基础知识详解(上)(如何想知道html的全部基础知识点,那么只看这一篇就足够了!)

前言&#xff1a;在学习前端基础时&#xff0c;必不可少的就是三大件&#xff08;html、css、javascript &#xff09;&#xff0c;而HTML&#xff08;超文本标记语言——HyperText Markup Language&#xff09;是构成 Web 世界的一砖一瓦&#xff0c;它定义了网页内容的含义和…