【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号信号被称为管理员信号,不可被自定义,只能执行默认动作


相关文章
|
14天前
|
缓存 监控 Linux
linux进程管理万字详解!!!
本文档介绍了Linux系统中进程管理、系统负载监控、内存监控和磁盘监控的基本概念和常用命令。主要内容包括: 1. **进程管理**: - **进程介绍**:程序与进程的关系、进程的生命周期、查看进程号和父进程号的方法。 - **进程监控命令**:`ps`、`pstree`、`pidof`、`top`、`htop`、`lsof`等命令的使用方法和案例。 - **进程管理命令**:控制信号、`kill`、`pkill`、`killall`、前台和后台运行、`screen`、`nohup`等命令的使用方法和案例。
44 4
linux进程管理万字详解!!!
|
5天前
|
存储 运维 监控
深入Linux基础:文件系统与进程管理详解
深入Linux基础:文件系统与进程管理详解
41 8
|
13天前
|
算法 Linux 定位技术
Linux内核中的进程调度算法解析####
【10月更文挑战第29天】 本文深入剖析了Linux操作系统的心脏——内核中至关重要的组成部分之一,即进程调度机制。不同于传统的摘要概述,我们将通过一段引人入胜的故事线来揭开进程调度算法的神秘面纱,展现其背后的精妙设计与复杂逻辑,让读者仿佛跟随一位虚拟的“进程侦探”,一步步探索Linux如何高效、公平地管理众多进程,确保系统资源的最优分配与利用。 ####
46 4
|
14天前
|
缓存 负载均衡 算法
Linux内核中的进程调度算法解析####
本文深入探讨了Linux操作系统核心组件之一——进程调度器,着重分析了其采用的CFS(完全公平调度器)算法。不同于传统摘要对研究背景、方法、结果和结论的概述,本文摘要将直接揭示CFS算法的核心优势及其在现代多核处理器环境下如何实现高效、公平的资源分配,同时简要提及该算法如何优化系统响应时间和吞吐量,为读者快速构建对Linux进程调度机制的认知框架。 ####
|
16天前
|
消息中间件 存储 Linux
|
22天前
|
运维 Linux
Linux查找占用的端口,并杀死进程的简单方法
通过上述步骤和命令,您能够迅速识别并根据实际情况管理Linux系统中占用特定端口的进程。为了获得更全面的服务器管理技巧和解决方案,提供了丰富的资源和专业服务,是您提升运维技能的理想选择。
24 1
|
1月前
|
算法 Linux 调度
深入理解Linux操作系统的进程管理
【10月更文挑战第9天】本文将深入浅出地介绍Linux系统中的进程管理机制,包括进程的概念、状态、调度以及如何在Linux环境下进行进程控制。我们将通过直观的语言和生动的比喻,让读者轻松掌握这一核心概念。文章不仅适合初学者构建基础,也能帮助有经验的用户加深对进程管理的理解。
22 1
|
1月前
|
消息中间件 Linux API
Linux c/c++之IPC进程间通信
这篇文章详细介绍了Linux下C/C++进程间通信(IPC)的三种主要技术:共享内存、消息队列和信号量,包括它们的编程模型、API函数原型、优势与缺点,并通过示例代码展示了它们的创建、使用和管理方法。
30 0
Linux c/c++之IPC进程间通信
|
1月前
|
Linux C++
Linux c/c++进程间通信(1)
这篇文章介绍了Linux下C/C++进程间通信的几种方式,包括普通文件、文件映射虚拟内存、管道通信(FIFO),并提供了示例代码和标准输入输出设备的应用。
26 0
Linux c/c++进程间通信(1)
|
1月前
|
Linux C++
Linux c/c++进程之僵尸进程和守护进程
这篇文章介绍了Linux系统中僵尸进程和守护进程的概念、产生原因、解决方法以及如何创建守护进程。
20 0