【Linux】进程信号(上)(一)

简介: 【Linux】进程信号(上)

1.信号概念理解

信号产生

什么叫做信号呢?

生活当中认为是信号的是:红绿灯 闹钟 下课铃 鸡叫 手势

1.当红灯亮的时候, 你会停下来 即匹配的动作

那为什么会有这个匹配动作呢?

因为曾经有人培养过你

所以信号没有被产生,也知道怎么该处理它


2.我们能够认识并处理一个信号,是能因为识别这个信号的


若进程就是我,信号就是一个数字,进程在没有接收信号的时候,它早就知道一个信号该如何处理了

程序员在设计进程的时候,早就已经设计了对信号的识别能力


3.因为信号可能随时产生,所以在信号产生前,我可能正在做优先级更高的事情,我可能不能立马处理信号

要在后续合适的时候进行处理


如:你点了一份外卖,因为你不确定外卖什么时候到,所以开了一把游戏,当外卖小哥给你打电话说外卖到了时,游戏还没打完,所以你跟外卖小哥说等一会,马上到,然后继续打游戏,直到游戏打完,才去取外卖


信号保存


4a18d0e8648c4c058e394f50fbc0031f.png

在信号产生和信号处理之间,存在时间窗口,因为没办法直接处理,需要等待后续处理

在时间窗口期间,需要被保存起来


进程收到信号的时候,如果没有立马处理这个信号,需要进程具有记录信号的能力


信号的产生对于进程来讲是异步的


异步为两者互相做自己的事,互不干扰

如:你正在上课,外卖小哥给你打电话告诉你快递到了,因为快递有重要的东西,所以你不得不现在去取,但是在你取快递的过程中,依旧在上课,上课与你取快递两件事情互不干扰


进程该如何记录对应产生的信号?记录在哪里?


可能同时收到很多信号,已经被产生但尚未处理,所以需要在时间窗口内,将这些信号保存,同时也应该将其进行管理

而管理的本质是先描述,在组织

那如何描述一个信号呢? 用什么数据结构管理这个信号呢?


输入 kill -l 查看信号列表


7845a99154624b22b53ba3cf89376d17.png

可以发现在31 和34之间没有信号存在,说明信号被划分为两部分,1-31以及34-64

34-64称之为实时信号,

1-31称之为普通信号,是目前要学习的信号

数字实际上是真正的信号,而大写的名称是宏


实时操作系统

当前主流的操作系统分为实时和分时,

分时像Linux、windows操作系统,基于时间片操作器调度的,强调的是公平调度

实时 像汽车的车载系统的辅助驾驶

特点为若来一个任务,就必须优先级较高的将该任务立马处理,强调的是高响应

普通信号 ,只保存有无产生,只需在合适的时候处理信号即可


可以通过0代表没有产生,1代表产生

1-31刚好是32个比特位,所以使用位图结构管理信号

而进程使用task_struct(PCB) 内部必定要存在一个位图结构,用int表示


e775d28d82ab45da82ba18967f920850.png


从低到高的比特位,依次对应1-31 信号

发送信号的本质是写入信号,直接修改特定进程的信号位图中的特定比特位,0变成1即可

比特位的位置,称之为信号的编号

比特位的内容,表示是否收到该信号


信号处理

默认处理信号的方式:

1.默认动作

2.忽略信号

3.用户自定义动作

如:拿到快递,共有三种选择

1.执行默认动作把快递打开 2.忽略快递 3. 执行自定义动作(如快递内是零食,送给你的女朋友)

2. 信号的产生

在vscode中,创建makefile文件

mysignal:mysignal.cc
    g++ -o $@ $^
.PHONY:clean
clean:
    rm -f mysignal

创建 mysignal.cc(以cc结尾是cpp) 文件

会一直循环打印一句话,并当前进程的包含pid值

#include<iostream>
#include<unistd.h>
using namespace std;
int main()
{
   while(true)
   {
    cout<<"我是一个进程,我正在运行...,pid值:"<<getpid()<<endl;
    sleep(1);
   }
    return 0;
}

复制SSH渠道创建终端2,在保证运行终端1的可执行程序的情况下,

在终端2中输入 kill -9 +pid值 ,终止了终端1中运行的程序

9b4b44332c1f42a79e378d5f248f36a5.png


8a69448be7cd4f988d64ed882b076810.png


实际上 在键盘中输入 CTRL C ,终止运行程序,本质也是向对前台进程发送信号


2dbb85a1a0c841429f8c8e36cb6ca8ac.png


Linux通过远程终端访问时,只允许一个进程处于前台,默认情况是bash,

所以在自己的程序运行时输入指令没有任何反应


证明输入 CTRL C 就是向前台进程发送信号

输入 man 2 signal 指令


82e0a96dcaac4402a4f0e9fd513d8caa.png


第二个是一个函数指针 将 void(*) (int) typedef 命名为 sighandler_t

signal 函数的第一个参数 是 signsum 代表信号编号

第二个参数 是 handler 代表哪一个进程调用了signal,使指定信号不在执行默认动作,而是执行该函数指针指向的方法


输入 CTRL C 相当于发送 2号信号


修改 mysignal.cc文件内容,并运行程序 发现输入 CTRL C 指令无法结束程序


77dc6362ec1d40f7ac58ef211a390ddb.png

91444f691e8f400298b8aedf8468f0dd.png

同样在终端2中输入 kill -2 pid值,也无法结束运行程序

说明对于2号信号 ,进程的默认方法是终止进程

signal 可以进行对指定动作的信号设定自定义处理动作

signal 函数内部参数传递的理解


76facb1bf7794bf0ba3eed8ebe3be66c.png

当signal(2,handler)调用完这个函数时, handler方法没有被调用,只是发生了回调

handler作为函数的地址传过去 作为参数被函数指针接收,再通过函数指针找到handler函数 完成调用

在操作系统内部,把对应的自定义方法的地址保存起来了


handler方法什么时候被调用?

当2号信号产生的时候

如: 你小时候总喜欢在家里调皮,你老爸不管你,认为这是很正常的事情,所以你认为这是默认动作,但是你的老妈看见你调皮,就告诉你说如果下次再看见你调皮,就揍你,

所以再有调皮捣蛋事情发生,不会像你老爸那样什么都不管,你老妈会揍你

是在下次调皮发生的时候,才揍你


对于信号自定义动作的捕捉问题

默认对2号信号的处理动作:终止进程

输入 man 7 signal 指令

f544f273fefa4d019f1c072dd60c83cf.png

2号信号的动作是 Term(终止)

用signal(2,handler),是在执行用户动作的自定义捕捉


878ff5b58f9f4f7ba701282aff92ad73.png


CTRL \ 代表3号信号 ,此时虽然2号信号被置为自定义动作了,但是三号信号还没有,所以依旧能终止进程


修改mysignal.cc文件内容,加入对于3号信号的自定义动作


48a1dacbcb8b41419f3a61d69d18c61f.png

89a3e6623761443482158a12e81eb96f.png


再次运行可执行程序时,发现使用CTRL \ 也会调用自定义动作


77c71f72cb314752af5caf0e0f2c856c.png


可以给所有信号设置同一个处理函数


若修改mysignal.cc文件内容,将1-31的所有普通信号都进行自定义动作捕捉

9dc39ce952ef4734b12af33213ef6529.png


15976f75b1a84035b374efbd14fe60ba.png


可当运行可执行程序时,在终端2中使用 kill -9 pid值 方式依旧可以干掉进程


9号信号被称为管理员信号,不可被自定义,只能执行默认动作


相关文章
|
7月前
|
安全 Linux
【Linux】阻塞信号|信号原理
本教程从信号的基本概念入手,逐步讲解了阻塞信号的实现方法及其应用场景。通过对这些技术的掌握,您可以更好地控制进程在处理信号时的行为,确保应用程序在复杂的多任务环境中正常运行。
252 84
|
6月前
|
并行计算 Linux
Linux内核中的线程和进程实现详解
了解进程和线程如何工作,可以帮助我们更好地编写程序,充分利用多核CPU,实现并行计算,提高系统的响应速度和计算效能。记住,适当平衡进程和线程的使用,既要拥有独立空间的'兄弟',也需要在'家庭'中分享和并行的成员。对于这个世界,现在,你应该有一个全新的认识。
250 67
|
5月前
|
Web App开发 Linux 程序员
获取和理解Linux进程以及其PID的基础知识。
总的来说,理解Linux进程及其PID需要我们明白,进程就如同汽车,负责执行任务,而PID则是独特的车牌号,为我们提供了管理的便利。知道这个,我们就可以更好地理解和操作Linux系统,甚至通过对进程的有效管理,让系统运行得更加顺畅。
138 16
|
5月前
|
Unix Linux
对于Linux的进程概念以及进程状态的理解和解析
现在,我们已经了解了Linux进程的基础知识和进程状态的理解了。这就像我们理解了城市中行人的行走和行为模式!希望这个形象的例子能帮助我们更好地理解这个重要的概念,并在实际应用中发挥作用。
108 20
|
4月前
|
监控 Shell Linux
Linux进程控制(详细讲解)
进程等待是系统通过调用特定的接口(如waitwaitpid)来实现的。来进行对子进程状态检测与回收的功能。
86 0
|
4月前
|
存储 负载均衡 算法
Linux2.6内核进程调度队列
本篇文章是Linux进程系列中的最后一篇文章,本来是想放在上一篇文章的结尾的,但是想了想还是单独写一篇文章吧,虽然说这部分内容是比较难的,所有一般来说是简单的提及带过的,但是为了让大家对进程有更深的理解与认识,还是看了一些别人的文章,然后学习了学习,然后对此做了总结,尽可能详细的介绍明白。最后推荐一篇文章Linux的进程优先级 NI 和 PR - 简书。
118 0
|
4月前
|
存储 Linux Shell
Linux进程概念-详细版(二)
在Linux进程概念-详细版(一)中我们解释了什么是进程,以及进程的各种状态,已经对进程有了一定的认识,那么这篇文章将会继续补全上篇文章剩余没有说到的,进程优先级,环境变量,程序地址空间,进程地址空间,以及调度队列。
84 0
|
4月前
|
Linux 调度 C语言
Linux进程概念-详细版(一)
子进程与父进程代码共享,其子进程直接用父进程的代码,其自己本身无代码,所以子进程无法改动代码,平时所说的修改是修改的数据。为什么要创建子进程:为了让其父子进程执行不同的代码块。子进程的数据相对于父进程是会进行写时拷贝(COW)。
82 0
|
7月前
|
Linux 数据库 Perl
【YashanDB 知识库】如何避免 yasdb 进程被 Linux OOM Killer 杀掉
本文来自YashanDB官网,探讨Linux系统中OOM Killer对数据库服务器的影响及解决方法。当内存接近耗尽时,OOM Killer会杀死占用最多内存的进程,这可能导致数据库主进程被误杀。为避免此问题,可采取两种方法:一是在OS层面关闭OOM Killer,通过修改`/etc/sysctl.conf`文件并重启生效;二是豁免数据库进程,由数据库实例用户借助`sudo`权限调整`oom_score_adj`值。这些措施有助于保护数据库进程免受系统内存管理机制的影响。
|
7月前
|
存储 Linux 调度
【Linux】进程概念和进程状态
本文详细介绍了Linux系统中进程的核心概念与管理机制。从进程的定义出发,阐述了其作为操作系统资源管理的基本单位的重要性,并深入解析了task_struct结构体的内容及其在进程管理中的作用。同时,文章讲解了进程的基本操作(如获取PID、查看进程信息等)、父进程与子进程的关系(重点分析fork函数)、以及进程的三种主要状态(运行、阻塞、挂起)。此外,还探讨了Linux特有的进程状态表示和孤儿进程的处理方式。通过学习这些内容,读者可以更好地理解Linux进程的运行原理并优化系统性能。
241 4