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

Linux -- 初识信号

目录

什么是信号?

如何使用信号?

代码:

testSig.cc

makefile: 

验证:

2号信号:

9号信号:

建立对信号的认识:

信号的处理

自定义信号的处理方式:

signal 函数:

参数

返回值

代码1(以2号信号为例):

验证1:

代码2:

验证2:

 ​编辑

忽略信号: 

代码:

验证:


什么是信号?

信号是 Linux 系统提供的、让用户(进程)给其他进程发送异步信号的一种方式,用于通知进程发生了某个事件


异步:一种编程模型或操作模式,在这种模式下,任务的执行不会阻塞或等待其他任务完成,而是独立进行,并且可以在任务完成时通过回调、事件或其他机制通知主程序。

指令 kill -l 可以查看 Linux 中的信号,可以注意到,没有 0号、32号、33号信号,且从 34号信号开始,信号名字中都带有 RT

如何使用信号?

下面用简单的代码来认识一些常见的信号:

代码:

testSig.cc

#include<iostream>
using namespace std;
#include<unistd.h>
#include<sys/types.h>
int main()
{while(1){cout<<" I am activing ... pid: "<<getpid()<<endl;sleep(1);}return 0;
}

makefile: 

testSig:handlerSig.ccg++ -o $@ $^ -std=c++11.PHONY:clean
clean:rm -f testSig

验证:

指令 kill -signal pid 就可以向指定进程发送信号。

2号信号:

2号信号在Linux系统中对应的是 SIGINT(Interrupt Signal),通常被称为中断信号,用于请求中断正在运行的程序。 

可以看出,死循环的进程在收到信号后结束死循环,进程终止: 

指令必须带 pid,不能是进程名: 

指令中的 -signal 可以是数字,也可以是信号的名字(即宏定义): 

9号信号:

9号信号在Linux系统中对应的是 SIGKILL 信号,是一个强制终止信号,用于立即终止进程

进程收到信号后,会打印 "Killed": 

 

建立对信号的认识:

初步了解了什么是信号后,我们需要建立以下对信号的认识: 

1、还没有向指定进程发送信号时,进程已经知道收到信号时,该怎么处理了

2、信号能够被识别出来,也就是说,编写内核的才程序员提前给进程设定好了识别特定信号的方式;

3、进程收到信号时,如果进程正在处理更重要的事情,进程可以暂时不处理收到的信号,但是进程必须临时保存该信号

4、进程收到信号时,可以不立即处理,可以在合适的时候处理

5、信号可以随时产生!我们无法预测信号什么时候发送,所以信号是异步发送的

以上的认识可以结合日常生活的例子理解,比如,把早起的闹钟设为一种信号,我们在闹钟响之前,已经知道听到闹钟时该怎么处理这个信号了,那就是起床,我们也可以先不起床,等到想起床的时候再起床,而且,我们在睡梦中无法预测闹钟什么时候会响。 

信号的处理

从上面两个信号的例子可以看出,进程收到不同的信号后,有不同的处理方式,而以上的信号处理方式,是信号处理的默认动作,我们还可以捕捉信号,自定义信号的处理方式,或者忽略信号!

自定义信号的处理方式:

signal 函数:

signal 函数是 Linux 系统中用于设置信号处理函数的简单接口。它允许你指定当进程接收到某个信号时应调用哪个函数,而不是默认的信号处理方式

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

signum: 要处理的信号编号

handler: 信号处理函数的指针,类型为 void (*)(int)。这个函数会在接收到指定信号时被调用,也就是说,如果进程没有收到指定信号,handler 函数将永远不会被调用

返回值

成功: 返回之前的信号处理函数指针

失败: 返回 SIG_ERR,此时 errno 会被设置为相应的错误码。

代码1(以2号信号为例):

#include<iostream>
using namespace std;
#include<unistd.h>
#include<sys/types.h>
#include<signal.h>void handler(int signo)
{cout<<" I got a signal,signo:"<<signo<<endl;
}
int main()
{signal(SIGINT,handler);while(1){cout<<" I am activing ... pid: "<<getpid()<<endl;sleep(1);}return 0;
}

验证1:

代码2:

在代码1的基础上,设置了退出码

#include<iostream>
using namespace std;
#include<unistd.h>
#include<sys/types.h>
#include<signal.h>void handler(int signo)
{cout<<" I got a signal,signo:"<<signo<<endl;exit(100);
}
int main()
{signal(SIGINT,handler);while(1){cout<<" I am activing ... pid: "<<getpid()<<endl;sleep(1);}return 0;
}

验证2:

进程结束后,当我们查看退出码时,退出码为100:

 

忽略信号: 

只需要在 signal 的 handler 参数传入 SIG_IGN,即可忽略指定的信号

代码:

#include<iostream>
using namespace std;
#include<unistd.h>
#include<sys/types.h>
#include<signal.h>int main()
{signal(SIGINT,SIG_IGN);while(1){cout<<" I am activing ... pid: "<<getpid()<<endl;sleep(1);}return 0;
}

验证:

可以看出,当我们向进程发送 2号信号时,进程忽略了 2号信号,不做任何处理,于是发送 9号信号终止进程!

http://www.lryc.cn/news/476378.html

相关文章:

  • Ubuntu系统如何实现键盘按键映射到其他按键(以 Ctrl+c 映射到 F3,Ctrl+v 映射到 F4 为例)
  • el-select、el-autocomplete的选项内容过长显示完整内容
  • Go-单元测试
  • 【Linux】IPC 进程间通信(一):管道(匿名管道命名管道)
  • Kotlin类与对象
  • Windows版 nginx安装,启动,目录解析,常用命令
  • 基于51单片机的电子隐形防盗网proteus仿真
  • Fish Agent:多语言 Voice-to-Voice 开源语音模型;Runway 推出摄像机运镜功能丨 RTE 开发者日报
  • locust压测工具环境搭建(Linux、Mac)
  • 欠定方程有多个真正解,超定方程可能无解所以有最小二乘解
  • LeetCode27:移除元素
  • JAVA 插入 JSON 对象到 PostgreSQL
  • 视图,物化视图,普通表区别简介
  • C++ | Leetcode C++题解之第530题二叉搜索树的最小绝对差
  • 使用Node.js构建实时聊天应用
  • STM32F103C8T6学习笔记1--新建工程模板
  • RK3568平台开发系列讲解(内存篇)Linux 内存优化
  • 企业数字化转型实施中的挑战与解决方案:架构引领的战略路径
  • 《数字图像处理基础》学习05-数字图像的灰度直方图
  • 【漏洞复现】某平台-QRcodeBuildAction-LoginSSO-delay-mssql-sql注入漏洞
  • Centos安装ZooKeeper教程(单机版)
  • A011-基于SpringBoot的视频点播系统设计与实现
  • 云原生+AI核心技术&最佳实践
  • 【Android】Service
  • 2-142【软件无线电原理与应用作业】基于matlab的圆形阵列的波束形成进行仿真
  • 在目录中按扩展名分类文件(python学习)(11.1)
  • 【网络安全 | 漏洞挖掘】逻辑漏洞+无限制爆破实现业务瘫痪
  • 【WRF工具】MPAS(多尺度预测模型)-输出WRF初始和横向边界条件
  • 分数阶傅里叶变换与信息熵怎么用于信号处理?
  • web3.0 开发实践