首页 > 其他分享 >信号初解

信号初解

时间:2022-11-20 22:02:13浏览次数:47  
标签:注册 初解 自定义 处理 可靠 信号 进程

       今天为大家带来的是我学习完Linux中信号章节的相关知识,主要内容有:信号的概念,信号的产生,注册,注销,处理和阻塞,并且还有应用等知识点。本次使用的编程语言为C语言,使用的操作系统为Linux操作系统。

信号的概念

       信号:是一种软件中断,也是一种时间的通知机制。通知进程发生了某件事,打断进程当前的操作,然后去处理这件事。

       上述的解释可能有点模糊,我们可以这样理解:当我们的电脑运行一个程序时,我们点击关闭程序,我们“点击关闭”的动作就是向电脑发送一个信号,那个信号就是“关闭程序”。

       接下来我们来看看信号的种类,打开我们的Linux,输入代码即可看到全部种类的信号,共62种:

Kill -l//查看全部信号指令

信号初解_信号

       其中,用红色圈出的信号为非可靠信号,即非实时信号;没有圈出的则是可靠信号,即实时信号,其中的区别我会在注册中给出说明。这些信号的左右我们可以通过代码找到解释:

man 7 signal//信号解释

       一个信号的生命周期为:产生,注册,注销和处理,另外还有特殊的阻塞状态,下面我们就来一一刨析每个信号的每个阶段到底经历了什么。

产生

信号的产生可分为两类:硬件产生和软件产生。

硬件产生包括:

       CTRL+C(从键盘中输入SIGINT信号,中断进程)

       CTRL+Z(从键盘中输入SIGTSTP信号,停止进程运行)

       CTRL+\(从键盘中输入SIGQUIT信号,使进程退出)

软件产生:就是通过kill -signum pid命令对指定进程发送信号,还可以通过kill(),raise(),abort(),alarm()函数对进程发送信号,感兴趣的hxd可以自己查阅这些函数的功能。

       这里我们要说下kill命令,本质使默认给进程发送一个终止信号,进程接收到信号后,进行处理,处理结果就是退出。但是有三种情况,kill命令不能退出信号:1.僵尸进程,我们无法杀死已经死去的进程。2.进程处于停止状态,对发送的信号不做处理。3.信号可能被阻塞或被自定义处理。

注册

       信号的注册,主要是为了让进程知道自己接收了某种信号,本质就是在进程pcb种做出相应位置的标记。下面我们来详细说明并解释非可靠信号和可靠信号的区别。

       进程中的pcb中有一个sigpending(未决信号集),即位图,会标记出进程接收到了某个信号,其次还有一个sugqueue链表,会添加一个信号的信息节点。当有一个信号被进程接收时,位图会在相应的位置置1,并在链表中添加节点。这就是信号注册的本质。(未决信号:还没有被处理的信号)

信号初解_信号_02

其次就是可靠信号,当有可靠信号注册时,如果没有信号注册,位图置1,并添加节点;如果有节点注册,直接添加信号节点即可。

对于非可靠信号,当有信号没有被注册时,位图置1,并添加节点;如果有节点被注册时,直接丢弃该信号。

这就是可靠和非可靠的区别,即是否丢失数据。

       举个例子,当我们是一个进程睡眠30秒,我们使用kill命令,系统会直接发送信号打断休眠,去处理kill信号—退出;而当我们使用CTRL+Z进入停止状态,再使用kill命令,此时出现的情况为1.信号以被注册,只是没有被处理2.一旦解除阻塞,则信号直接被处理,杀死进程。

注销

       信号注销,也就是消除信号在未决信号集中的痕迹,防止系统重复处理。注销也分为两类:可靠信号的处理和非可靠信号的处理。

非可靠信号的注销:由于位图中每种非可靠信号只能有一个,所以非可靠信号的处理为删除信号节点,将位图置0。

可靠信号的注销:删除信号节点,并判断是否有相同节点存在,若没有则位图置0。

处理

信号的处理:调用信号的事件处理函数。总共分为三大类:

1.默认处理:系统中已经预定义好的处理方式

2.忽略处理:空的处理方式

3.自定义处理:程序员自定义的一个处理方式,替换原有的处理方式

我们这里说明下忽略处理和自定义处理。

       忽略处理最典型的就是SIGCHLD信号,当子进程推出后,默认给父进程的就是SIGCHLD信号,父进程接收信号后,就会忽略子进程的退出,从而导致僵尸进程的产生。

下面我们来演示自定义进程如何书写:

首先介绍接口:

信号初解_信号_03

接下来我们来实现代码:

#include<stdio.h>
#include<signal.h>
#include<unistd.h>
void sigcb(int n)//handler函数的格式
{
printf("n:%d\n",n);
}
int main()
{
signal(SIGINT,sigcb);//替换中断信号
while(1)
{
printf("hello world!\n");
sleep(1);
}
return 0;
}

当我们CTRL+C退出时,就会出现程序替换,进程不退出。

信号初解_信号_04

阻塞

       阻塞,是进程的一种状态,该状态可以使进程接收到的数据不被处理,但是信号依旧可以被注册。

       进程pcb中有个block阻塞信号集合,如果有信号被阻塞就会添加到block阻塞集合中,当处理信号时,就不会处理该信号。

信号初解_信号_05

       下面我们就来实现阻塞状态下进程接收信号的过程,该过程不太好直观体现,所以我们使用上述signal函数,进行信号替换,让大家可以直观看出问题。

首先来介绍下接口:

信号初解_信号_06

下来我们开始写代码:

#include<stdio.h>
#include<signal.h>
#include<unistd.h>

void sigcb(int n)//替换的函数handler
{
printf("recv signal:%d\n",n);
}
int main()
{
signal(SIGINT,sigcb);
signal(SIGRTMIN+5,sigcb);

sigset_t set,old;//定义两信号集合

sigemptyset(&set);//清空定义的信号集合
sigemptyset(&old);
sigfillset(&set);//将所有信号填充到set中

sigprocmask(SIG_BLOCK,&set,&old);//将set中的信号阻塞
printf("按回车,继续运行!!!\n");
getchar();
sigprocmask(SIG_SETMASK,&old,NULL);//将原先的进程状态替换
while(1)
{
sleep(1);
}
return 0;
}

我们运行程序,我们发送设定好的信号自定义处理,就可以看到进程中没有信号被处理;当我们嗯下回车,信号就会被处理。

信号初解_信号_07

应用

下面我们来说两个比较常见的信号应用吧

1.自定义或者忽略处理SIGPIPE信号,例如:管道所有写端都被关闭,继续write就会触发异常。

2.自定义或者忽略处理SIGCHLD信号,例如:子进程退出时给父进程发送信号,然后称为僵尸进程。可以将SIGCHLD信号自定义为SIG_IGN信号,系统就会在子进程退出后默认直接处理,就不会发生僵尸进程。

我们再来看看上述所讲的自定义处理方式的信号捕捉流程,一幅图直接解决

信号初解_信号_08

好了,本次信号的内容就到这里,希望大家可以从中学到知识。如果有什么不对的地方,希望大佬可以批评指正!!!

标签:注册,初解,自定义,处理,可靠,信号,进程
From: https://blog.51cto.com/u_15209404/5872070

相关文章

  • Qt基础之四:Qt信号与槽机制原理及优缺点
    信号和插槽用于对象之间的通信。信号和槽机制是Qt的核心特性,可能也是与其他框架提供的特性最大不同的部分。Qt的元对象系统使信号和槽成为可能。一.简介在GUI编程中,当我们改......
  • 【DNN,OFDM检测】基于DNN深度学习网络的OFDM信号检测算法的matlab仿真
    1.软件版本matlab2021a2.部分核心代码      3.部分代码clearvariables;closeall;load('TrainingData.mat');load('ValidationData.mat');%%Definetr......
  • luoguP1269 信号放大器
    神奇的题目想了3个做法假·贪心、真·DP、真·贪心全部交上去分别获得40、90、100的好成绩蚌埠住了1.假·贪心考虑从孩子节点开始一直到指定的根节点u到中途某个节......
  • FPGA ——防止信号被优化(转载)
    转载:https://blog.csdn.net/weixin_46062412/article/details/125299437Quartus对这种情况的处理是增加约束,共有2种情况:a,需要保留的信号类型是wire在定......
  • Linux下进程间通信方式之管道、信号、共享内存、消息队列、信号量、套接字
    /*1,进程间通信(IPC)Inter-ProcessCommunication比较好理解概念的就是进程间通信就是在不同进程之间传播或交换信息。2,linux下IPC机制的分类:管道、信号、共享内存、......
  • 服务器端信号编程
    服务器端程序通常需要处理信号,关于信号的概念不多说,linux操作系统默认有64个信号,用kill-l可列出所有信号,信号是个异步机制的东西,我们这里的信号指的是操作系统给进程或者......
  • 转速测量脉冲信号采集 Modbus模块 编码器脉冲计数器pnp/npn转485
    特点:●编码器解码转换成标准ModbusRTU协议●可用作编码器计数器或者转速测量●支持编码器计数,可识别正反转●也可以设置作为2路独立DI高速计数器●计数值支持断电自动......
  • 进程间通信-信号-pipe-fifo
    一、管道(pipe)1、管道的定义和特点管道是一种两个进程间进行单向通信的机制。因为管道传递数据的单向性,管道又称为半双工管道。管道的这一特点决定了器使用的局限性。管......
  • 进程间通信-信号-pipe-fifo
    进程间通信-信号-pipe-fifopipepipe只能用于有血缘关系的进程进行单向通信。调用pipe函数时在内核中开辟一块缓冲区(称为管道)用于通信,它有一个读端一个写端,然后通过fd......
  • 进程间通信-信号-pipe-fifo
    1.信号signal1、信号的名字和编号:每个信号都有一个名字和编号,这些名字都以“SIG”开头,例如“SIGIO”、“SIGCHLD”等等。信号定义在signal.h头文件中,信号名都定义为正......