Linux--信号

一.引号的产生

1.什么是信号

在生活中,信号的产生是多种多样的,比如红绿灯,闹钟等等,Linux中的信号是什么呢?

1.在Linux中,信号的本质是一种通信方式,由用户或操作系统发送信号,通知进程,某些事情已经发生,同事进程在合适的时间以合适的方式进行处理。信号本身,可能不会被立即处理,也一定要被保存下来。操作系统可以识别这些信号。

2.结合进程,分析信号

a.进程要分析信号,必须要识别信号即,进程要接收并且要具备其如何处理的动作。

b.进程如何识别信号呢?通过程序员设置的方式让进程去识别。

c.信号的产生是随机的,所以进程的处理方式可能不是立即处理,而是将信号存储起来,在合适的场合处理。

d.进程会降临是信号进行存储,方便之后的处理。

e.一般而言,信号的产生相对于进程来说是异步的。

2.信号的产生

a,通过键盘的组合键产生

比如:通过Ctrl+c终止进程,这就是一种通过键盘向进程发送信号,让进程退出了。

处理信号的常见方式:

默认;忽略;自定义一共有这三种处理方式。

如何理解这些组合键是如何变成信号的?

键盘的工作方式是通过中断的方式进行的,OS解释组合键,然后在进程列表中查找,找到前台运行的进程,OS将信号写入当前的进程结构中的位图中。

常见的信号:

前31个信号为普通信号,后31个信号为实时信号。

如何理解信号被进程保存

进程必须具有保存信号的相关数据结构的位图,进程PCB内部保存了信号,信号发送的本质是OS向目标进程发送对行的信号。OS修改进程内部PCB所对应的位图结构,完成发送进程的过程。

键盘产生的信号:

signal函数:signal(int signum, sighandler_t handler);

第一个参数为信号,可以是信号的编号,也可以是信号的名称,第二个参数是一个回调函数,通过回调函数处理信号,可以为默认,忽略,自定义。默认和忽略所对应的参数名称为:SIG_DFL,SIG_IDO。自定义的参数需要自己写回调函数去完成。通过回调的方式,去修改对应的信号捕捉方法。

比如:

static void handle(int signam)
{
  std::cout<<"我是一个进程"<<std::endl;
}

int main(int argc,const char* argv[])
{
  signal(2,handle);//信号函数
  if(argc!=3)
  {
   while(true)
      sleep(1);
  }
  return 0;
}

默认处理动作是终止进程并且Core Dump(核心转储)

Core Dump是什么?

当一个进程要异常终止时,可以选择把进程的用户空间内存数据全部 保存到磁盘上,文件名通常是core,这叫做Core Dump。我们可以通过使用gdb调试查看core文件查看进程退出的原因,这也叫事后调试

Core Dump使用演示:
一个进程允许产生多大的core文件取决于进程的Resource Limit,这个信息报错在PCB中。默认情况下,不允许产生core文件,因为core文件中比较大(容易浪费资源),包含用户密码等敏感信息,不安全。我们可以通过命令ulimit -a 查看系统允许我们产生多大的core文件。

可以发现的是,系统是不允许产生这个core文件的,但是我们可以通过命令ulimit -c size 修改,允许产生size大小的core文件。
下面我们写一个程序验证一下:

int main(int argc,const char* argv[])
{
  signal(2,SIG_DFL);
  if(argc!=3)
  {
    while(true)
     { 
        cout<<"Hello word"<<endl;
        sleep(1);
     }
  }
  return 0;
}

结果:

core dumped标志是否发生核心转储。主要是为了调试。

可以看到core.2549这个文件很大,所以在一般生产环境下都需要关闭核心转储功能。

b.系统调用接口产生信号

用户调用系统接口,执行OS所对应的代码,OS设置参数,OS向目标进程写入,OS修改对应的位图结构,进程后续执行所对应的信号。介绍三个系统调用函数 kill函数 raise函数 abort函数。

kill函数

给任意进程发送任意信号

#include <signal.h>

int kill(pid_t pid, int sig);

参数:pid 进程pid sig 要发送的信号

raise函数

给进程自己发送信号

#include <signal.h>  
int raise(int sig);  
  • 1
  • 2

参数:

  • sig:要发送的信号

返回值: 成功返回0,失败返回-1
和kill比较:

 raise函数相当于kill(getpid(), sig)  

abort函数

功能: 使用当前进程收到信号而异常终止(发送6号信号)
函数原型:

#include <stdlib.h>  
void abort(void); 

c.由软件条件产生信号

SIGPIPE是一种由软件条件产生的信号,在“管道”中已经介绍过了。主要介绍alarm函数 和SIGALRM信号。

alarm函数

int main()
{
  //signal(SIGALRM, handler);
  alarm(5);
  //int count=0;
  while(true)
  {
    count++;
    cout<<"count:"<<count<<endl;
    sleep(1);
  }
}

结果:

所以:

功能: 设定一个闹钟,操作系统会在闹钟到了时送SIGALRM 信号给进程,默认处理动作是终止进程
函数原型:

#include <unistd.h> 
unsigned alarm(unsigned seconds); 
1
2
参数:

second:设置时间,单位是s
返回值: 0或者此前设定的闹钟时间还余下的秒数

d.硬件异常产生

硬件异常被硬件以某种方式被硬件检测到并通知内核,然后内核向当前进程发送适当的信号。
这里给大家介绍两个硬件异常:CPU产生异常 和 MMU产生异常

CPU产生异常 发生除零错误,CPU运行单元会产生异常,内核将这个异常解释为信号,最后OS发送SIGFPE信号给进程。

MMU产生异常: 当进程访问非法地址时,mmu想通过页表映射来将虚拟转换为物理地址,此时发现页表中不存在该虚拟地址,此时会产生异常,然后OS将异常解释为SIGSEGV信号,然后发送给进程。

2.信号的保存

捕捉信号

先思考一个问题:信号是什么时候被处理的

首先,不是立即被处理的。而是在合适的时候,这个合适的时候,具体指的是进程从用户态切换回内核态时进行处理。

  • 用户态: 处于⽤户态的 CPU 只能受限的访问内存,用户的代码,并且不允许访问外围设备,权限比较低。
  • 内核态: 处于内核态的 CPU 可以访问任意的数据,包括外围设备,⽐如⽹卡、硬盘等,权限比较高。
  • 注意: 操作系统中有一个cr寄存器来记录当前进程处于何种状态

进程空间分为用户空间和内核空间。此前我们介绍的页表都是用户级页表,其实还有内核级页表。进程的用户空间是通过用户级页表映射到物理内存上,内核空间是通过内核级页表映射到物理内存上。

进程有不同的用户空间,但是只有一个内核空间,不同进程的用户空间的代码和数据是不一样的,但是内核空间的代码和数据是一样的。
上面这些主要是想说:进程处于用户态访问的是用户空间的代码和数据,进程处于内核态,访问的是内核空间的代码和数据。

信号处理函数:

sigaction函数:

功能:可以读取和修改与指定信号相关联的处理动作
函数原型:

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

signum: 要操作的信号

act:一个结构体

sa_handler:SIG_DFT、SIG_IGN和handler(用户自定义处理函数)
sa_sigaction:实时信号处理的函数,我们不关心
sa_mask:一个信号屏蔽字,里面有需要额外屏蔽的的信号
sa_flags:包含一下选项,这里我们给0
sa_restorer:我们这里不使用。

结构体如下:

struct sigaction {
	void     (*sa_handler)(int);
    void     (*sa_sigaction)(int, siginfo_t *, void *);
    sigset_t   sa_mask;
    int        sa_flags;
    void     (*sa_restorer)(void);
};

返回值: 成功返回0,失败返回-1

3.信号的处理

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

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

相关文章

性格软弱怎么办?如何改变性格软弱?

软弱指的是身体衰弱无力气&#xff0c;而这里要说的是性格软弱&#xff0c;性格软弱的人&#xff0c;大多是不自信的&#xff0c;无主见&#xff0c;容易妥协&#xff0c;害怕产生矛盾&#xff0c;遇到问题就想逃避&#xff0c;自我否定&#xff0c;担心自己这也不行那也不行。…

vue+css动画 实现文字的上下轮播切换

突然间碰到一个比较丝滑的特效,就研究了一下想把它实现出来。 效果:渐隐消失,底部往上走覆盖出现 以下是完整代码,复制粘贴即可运行 <template><div class="aaa"><divclass="page1":class="{ private-fade-out: prevIndex === 1…

代码随想录算法训练营第四十七天丨 动态规划part10

121. 买卖股票的最佳时机 思路 动态规划 动规五部曲分析如下&#xff1a; 确定dp数组&#xff08;dp table&#xff09;以及下标的含义 dp[i][0] 表示第i天持有股票所得最多现金 &#xff0c;这里可能有疑惑&#xff0c;本题中只能买卖一次&#xff0c;持有股票之后哪还有…

Python大语言模型实战-利用ChatDev框架自动开发一个游戏软件(附完整教程)

实现功能 ChatDev一个由多智能体协作框架&#xff0c;是一个虚拟软件公司&#xff0c;在人类 “用户” 指定一个具体的任务需求后&#xff0c;不同角色的智能体将进行交互式协同&#xff0c;以生产一个完整软件&#xff08;包括源代码、环境依赖说明书、用户手册等&#xff09…

利用IP风险画像强化金融行业网络安全防御

在数字化时代&#xff0c;金融行业日益依赖互联网和技术创新&#xff0c;但这也使得金融机构成为网络攻击的主要目标。为了应对日益复杂的网络威胁&#xff0c;金融机构迫切需要采用先进的安全技术和工具。其中&#xff0c;IP风险画像技术成为提升网络安全的一项重要策略。 1.…

若依分离版——使用Knife4j 自动生成接口文档

背景&#xff1a; 前后端分离程序&#xff0c;如果需要前端开发人员和后端开发人员配合开发&#xff0c;则需要将接口文档并显性给前端人员 解决办法&#xff1a; 使用knife4j替代若依自带的swagger&#xff0c;因为knife4j是在swagger基础上包装的&#xff0c;Knife4j不仅具…

Django生鲜蔬菜采购系统-计算机毕设 附源码 24033

Django生鲜蔬菜采购系统 目 录 摘要 1 绪论 1.1 研究背景 1.2国内外研究现状 1.3论文结构与章节安排 2 生鲜蔬菜采购系统系统分析 2.1 可行性分析 2.1.1 技术可行性分析 2.1.2 经济可行性分析 2.1.3 操作可行性分析 2.2 系统流程分析 2.2.1 数据流程 3.3.2 业务流…

react类式组件的生命周期和useEffect实现函数组件生命周期

概念 生命周期是一个组件丛创建,渲染,更新,卸载的过程,无论是vue还是react都具有这个设计概念,也是开发者必须熟练运用的,特别是业务开发,不同的生命周期做不同的事是很重要的. ....多说两句心得,本人是先接触vue的,无论是vue2还是vue3的生命周期,在理解和学习上都会比react更…

【三维重建】摄像机几何

针孔相机模型 为了方便我们对针孔相机模型进行数学建模&#xff0c;我们往往对虚拟像平面进行研究&#xff0c;因为虚拟像平面的方向与我们实际物体的方向一致。 通过相似三角形法可以得到三维坐标到二维坐标映射 将像平面原点坐标移动到左下角&#xff1a; 加上现实世界单位&a…

Excel表列序号

题意&#xff1a; 给你一个字符串 columnTitle &#xff0c;表示 Excel 表格中的列名称。返回 该列名称对应的列序号 。 例如&#xff1a; A -> 1 B -> 2 C -> 3 … Z -> 26 AA -> 27 AB -> 28 … 示例 1: 输入: columnTitle “A” 输出: 1 示例 2: 输…

植物补光灯,哪种效果好?

室内种植物有诸多好处&#xff1a;空间装饰、吸收有害物质、释放氧气&#xff0c;使室内空气更加清新&#xff1b;植物的蒸腾作用可以增加室内的湿度&#xff0c;改善秋冬季干燥的室内环境&#xff0c;可谓是天然的加湿器。 然而由于缺乏太阳光&#xff0c;在室内养植并不是一…

Matlab设置figure中标题/图例英文不同字体

1.创建一个曲线图 x linspace(-10,10,200); y sin(4*x)./exp(x); plot(x,y) xlim([0 10]) ylim([-0.4 0.8]) xlabel(a); ylabel(b); title(曲线图sapi); set(gca,FontName,Times New Roman,fontsize,16); legend(曲线12)标题中既包含英文又包含中文&#xff0c;如果设置字体…

玩具品牌的国际化之路:市场推广战略解析

玩具产业一直是全球市场中备受瞩目的领域之一。随着全球化的发展和互联网的普及&#xff0c;越来越多的玩具品牌开始进军国际市场。这既是机遇&#xff0c;也是挑战。在竞争激烈的全球市场中&#xff0c;如何成功推广玩具品牌是一个关键的问题。本文Nox聚星将和大家探讨玩具品牌…

一台主机上只能保持最多 65535 个 TCP 连接吗?

大家好&#xff0c;我是老杨。 在知乎上刷到一个问题&#xff0c;叫做“一台主机上只能保持最多 65535 个 TCP 连接吗&#xff1f;” 关注度极高&#xff0c;想着咱们粉丝也一定有兴趣&#xff0c;就展开聊一聊。 对技术感兴趣&#xff0c;是做我们这一行必须要有的品质之一…

6大顶级团队计划目标管理软件盘点,全行业适用!

在快节奏的现代工作环境中&#xff0c;高效的团队计划和执行是团队取得成功的关键。然而&#xff0c;随着团队规模不断增大、工作任务不断增加&#xff0c;如何提高团队计划与效率成为了一个挑战。幸运的是&#xff0c;有许多先进的软件工具可以帮助团队更好地组织、协调和追踪…

【Python基础】基于UPD协议实现简易聊天室(Socket编程)

UDP通信 1.什么是 socket2. 创建 socket3.udp 网络程序-发送、接收数据&#xff08;User Datagram Protocol&#xff09;udp 网络程序-发送、接收数据&#xff08;客户端&#xff09;udp 绑定信息udp 绑定信息---服务器端总结 4.udp 聊天器 1.什么是 socket socket(简称 套接字…

遍历List集合和Map进行修改和删除报java.util.ConcurrentModificationException错误详解

一、异常产生 当我们使用foreach迭代一个ArrayList或者HashMap时&#xff0c;如果尝试对集合做一些修改操作&#xff08;例如删除元素或新增&#xff09;&#xff0c;可能会抛出java.util.ConcurrentModificationException的异常。 javapublic static void main(String[] args)…

ChatGPT显现“ Something went wrong. If this issue persists ...”什么原因?如何解决?

一、报错提示 Something went wrong. If this issue persists please contact us through our help center at help.openai.com. 二、解决方案 一般是代理节点出现问题 ChatGPT退出登录 关闭代理并重新启动代理 切换其他节点 清除浏览器缓存 重新登录ChatGPT 三、其它思路…

C# TabControl实现为每一个TabPage添加关闭按钮

默认情况下TabControl是无法通过界面关闭TabPage的 有些情况下我们需要手动关闭任意一个TabPage&#xff0c;如下图所示 TabControl控件自带属性是无法满足以上需求&#xff0c;下面简单介绍实现过程 1、首先需要对TabPage进行重绘&#xff0c;其目的是为了在TabPage上画出…

Linux学习第38天:Linux I2C 驱动实验(二):哥俩好

Linux版本号4.1.15 芯片I.MX6ULL 大叔学Linux 品人间百味 思文短情长 本节笔记主要学习I2C设备驱动编写及硬件原理图分析。 先把整个本节的思维导图贴出来&#xff1a; 二、I.MX6U的I2C适配器驱动分析 适配器驱动一般都是由SOC厂商提…
最新文章