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


相关文章
|
29天前
|
消息中间件 存储 网络协议
从零开始掌握进程间通信:管道、信号、消息队列、共享内存大揭秘
本文详细介绍了进程间通信(IPC)的六种主要方式:管道、信号、消息队列、共享内存、信号量和套接字。每种方式都有其特点和适用场景,如管道适用于父子进程间的通信,消息队列能传递结构化数据,共享内存提供高速数据交换,信号量用于同步控制,套接字支持跨网络通信。通过对比和分析,帮助读者理解并选择合适的IPC机制,以提高系统性能和可靠性。
107 14
|
2月前
|
算法 Linux 调度
深入理解Linux操作系统的进程管理
本文旨在探讨Linux操作系统中的进程管理机制,包括进程的创建、执行、调度和终止等环节。通过对Linux内核中相关模块的分析,揭示其高效的进程管理策略,为开发者提供优化程序性能和资源利用率的参考。
103 1
|
10天前
|
Linux
Linux编程: 在业务线程中注册和处理Linux信号
通过本文,您可以了解如何在业务线程中注册和处理Linux信号。正确处理信号可以提高程序的健壮性和稳定性。希望这些内容能帮助您更好地理解和应用Linux信号处理机制。
47 26
|
2天前
|
消息中间件 Linux C++
c++ linux通过实现独立进程之间的通信和传递字符串 demo
的进程间通信机制,适用于父子进程之间的数据传输。希望本文能帮助您更好地理解和应用Linux管道,提升开发效率。 在实际开发中,除了管道,还可以根据具体需求选择消息队列、共享内存、套接字等其他进程间通信方
32 16
|
1天前
|
Linux
Linux编程: 在业务线程中注册和处理Linux信号
本文详细介绍了如何在Linux中通过在业务线程中注册和处理信号。我们讨论了信号的基本概念,并通过完整的代码示例展示了在业务线程中注册和处理信号的方法。通过正确地使用信号处理机制,可以提高程序的健壮性和响应能力。希望本文能帮助您更好地理解和应用Linux信号处理,提高开发效率和代码质量。
32 17
|
1月前
|
消息中间件 Linux
Linux:进程间通信(共享内存详细讲解以及小项目使用和相关指令、消息队列、信号量)
通过上述讲解和代码示例,您可以理解和实现Linux系统中的进程间通信机制,包括共享内存、消息队列和信号量。这些机制在实际开发中非常重要,能够提高系统的并发处理能力和数据通信效率。希望本文能为您的学习和开发提供实用的指导和帮助。
104 20
|
2月前
|
存储 监控 Linux
嵌入式Linux系统编程 — 5.3 times、clock函数获取进程时间
在嵌入式Linux系统编程中,`times`和 `clock`函数是获取进程时间的两个重要工具。`times`函数提供了更详细的进程和子进程时间信息,而 `clock`函数则提供了更简单的处理器时间获取方法。根据具体需求选择合适的函数,可以更有效地进行性能分析和资源管理。通过本文的介绍,希望能帮助您更好地理解和使用这两个函数,提高嵌入式系统编程的效率和效果。
118 13
|
2月前
|
SQL 运维 监控
南大通用GBase 8a MPP Cluster Linux端SQL进程监控工具
南大通用GBase 8a MPP Cluster Linux端SQL进程监控工具
|
2月前
|
运维 监控 Linux
Linux操作系统的守护进程与服务管理深度剖析####
本文作为一篇技术性文章,旨在深入探讨Linux操作系统中守护进程与服务管理的机制、工具及实践策略。不同于传统的摘要概述,本文将以“守护进程的生命周期”为核心线索,串联起Linux服务管理的各个方面,从守护进程的定义与特性出发,逐步深入到Systemd的工作原理、服务单元文件编写、服务状态管理以及故障排查技巧,为读者呈现一幅Linux服务管理的全景图。 ####
|
3月前
|
缓存 算法 Linux
Linux内核的心脏:深入理解进程调度器
本文探讨了Linux操作系统中至关重要的组成部分——进程调度器。通过分析其工作原理、调度算法以及在不同场景下的表现,揭示它是如何高效管理CPU资源,确保系统响应性和公平性的。本文旨在为读者提供一个清晰的视图,了解在多任务环境下,Linux是如何智能地分配处理器时间给各个进程的。

热门文章

最新文章