【Linux】—— 信号的基本介绍(一)

简介: 【Linux】—— 信号的基本介绍(一)



(一)生活角度的信号

我们要学习有关信号的相关知识,首先要知道什么是信号。接下来我先从生活中的例子来带大家逐步认识。

在日常生活中,"信号" 这个词可以涵盖多个领域,以下是一些常见的生活中的信号:

  • 红绿灯、语言、姿态、表情 、鸟鸣、风声、情绪、闹钟、狼烟等等

就比如上诉的 红绿灯:我们都知道“红灯停,绿灯行”,对于不同的颜色都会匹配相应的动作。此时我就要问大家为什么会有这个动作呢?

  • 其实很简单,因为曾经有人或者有事等 “培养”过你,使你脑海中产生了这种印象,以至于即使现在不是身处红绿灯处,我们也知道不同的颜色我们该怎么进行处理!!

同理,若此时存在一个进程,而信号就是一个数字(可以通过 kill -l 查看,稍后会讲),即使进程没有收到信号的时候,它也知道当收到信号的时候能够准备识别并知道该如何处理(因为程序员设计进程的时候,早就已经设计好了对信号识别处理的能力!!)


如果大家还是困惑我在给大家举个例子:

  • 假设你在网上买了很多件商品,在等待不同商品快递的到来。但即便快递没有到来,你也知道快递来临时,你该怎么处理快递。也就是你能“识别快递”;
  • 当快递员到了你楼下,你也收到快递到来的通知,但是你正在打游戏,需5min之后才能去取快递。那么在在这5min之内,你并没有下去去取快递,但是你是知道有快递到来了。也就是取快递的行为并不是一定要立即执行,可以理解成“在合适的时候去取”;
  • 在收到通知,再到你拿到快递期间,是有一个时间窗口的,在这段时间,你并没有拿到快递,但是你知道有一个快递已经来了。本质上是你“记住了有一个快递要去取”;
  • 当你时间合适,顺利拿到快递之后,就要开始处理快递了。而处理快递一般方式有三种:1. 执行默认动作(幸福的打开快递,使用商品)2. 执行自定义动作(快递是零食,你要送给你你的女朋友)3. 忽略快递(快递拿上来之后,扔掉床头,继续开一把游戏);
  • 快递到来的整个过程,对你来讲是异步的,你不能准确断定快递员什么时候给你打电话.

(二)查看信号列表

 

我们可以使用kill -l命令可以察看系统定义的信号列表。具体如下:

【解释说明】

  1. 首先,在Linux系统中,【1-31】号的信号通常是标准的POSIX信号,大家也可以叫做普通信号(这是我们学习的主要);
  2. 其次,大家可以发现没有32、33号信号,31号之后就是34号。在POSIX标准中,并没有规定32和33号这样的信号,因此在通常的Linux系统中,这些数字对应的信号并没有特殊的含义。这并不是系统实际上没有定义更高编号的信号,而是在POSIX标准中未规定的部分给了系统一些灵活性,使得系统可以自定义和扩展信号的使用;
  3. 最后34号之后的统称为“实时信号”,对于这部分信号,大家可以不用关心;
  4. 最后大家也可以发现,每个都是以 数字开头紧跟一个大写的字符串。这里的数字就是“信号”,后面大写的字符串就是“宏”。
  1. SIGHUP (1): 挂起信号
  2. SIGINT (2): 中断信号
  3. SIGQUIT (3): 退出信号
  4. SIGILL (4): 非法指令信号
  5. SIGTRAP (5): 跟踪/断点陷阱信号
  6. SIGABRT (6): 中止信号
  7. SIGBUS (7): 总线错误信号
  8. SIGFPE (8): 浮点异常信号
  9. SIGKILL (9): 强制杀死进程信号
  10. SIGUSR1 (10): 用户自定义信号 1
  11. SIGSEGV (11): 段错误信号
  12. SIGUSR2 (12): 用户自定义信号 2
  13. SIGPIPE (13): 管道破裂信号
  14. SIGALRM (14): 超时信号
  15. SIGTERM (15): 终止信号
  16. SIGSTKFLT (16): 协程栈错误信号
  17. SIGCHLD (17): 子进程状态改变信号
  18. SIGCONT (18): 继续执行信号
  19. SIGSTOP (19): 停止进程信号
  20. SIGTSTP (20): 终端停止信号
  21. SIGTTIN (21): 后台进程尝试读取控制终端
  22. SIGTTOU (22): 后台进程尝试写入控制终端
  23. SIGURG (23): 紧急情况信号
  24. SIGXCPU (24): 超过CPU时间限制信号
  25. SIGXFSZ (25): 超过文件大小限制信号
  26. SIGVTALRM (26): 虚拟定时器信号
  27. SIGPROF (27): 用于分析的定时器信号
  28. SIGWINCH (28): 窗口大小改变信号
  29. SIGIO (29): 异步I/O事件通知信号
  30. SIGPWR (30): 电源故障信号
  31. SIGSYS (31): 非法系统调用信号

(三)技术应用角度的信号

有了上述的 知识储备之后,接下来通过简单的代码来理解信号!!!

 演示如下:

除了上述方法之外,还可以通过【ctrl+c】的方式终止一个前台进程

【现象解释】

  • 用户输入命令,在Shell下启动一个前台进程。
  • 用户按下【Ctrl+C】,,这个键盘输入产生一个硬件中断,被OS获取,解释成信号,发送给目标前台进程。前台进程因为收到信号,进而引起进程退出

【解释说明】

  • 前台进程是在终端中直接运行的进程,它会占用终端并接收来自用户的输入。通常,用户可以看到前台进程的输出,并且可以与之交互;
  • 前台进程的执行会阻塞终端,直到该进程完成或被暂停。

相应的也有后台进程(使用 & 将进程放到后台执行

  • 后台进程是在终端中以非阻塞方式运行的进程。用户可以继续输入命令和执行其他任务,而后台进程在后台默默执行;
  • 后台进程通常用于执行长时间运行的任务,而不占用用户的终端。

演示如下:

 

注意

  • 1. Ctrl-C 产生的信号只能发给前台进程。一个命令后面加个&可以放到后台运行,这样Shell不必等待进程结束就可以接受新的命令,启动新的进程。
  • 2. Shell可以同时运行一个前台进程和任意多个后台进程,只有前台进程才能接到像 Ctrl-C 这种控制键产生的信号。
  • 3. 前台进程在运行过程中用户随时可能按下 Ctrl-C 而产生一个信号,也就是说该进程的用户空间代码执行到任何地方都有可能收到 SIGINT 信号而终止,所以信号相对于进程的控制流程来说是异步(Asynchronous)的。

而此时,大家是否想到一点。对于 Ctrl-C 指令,默认执行的便是终端信号的作用,与我们的 2号信号的效果类似,那么到底是不是呢?我简单的演示下,将 2 号信号的默认执行动作改了,看是否和我们预想的类似。

代码展示:

#include<iostream>
#include<unistd.h>
#include <sys/types.h>
#include<signal.h>
void handle(int signa){
    std::cout << "get a siganl:" << signa << std::endl;
}
int main()
{
    signal(2,handle);
    while(true){
        std::cout << "我是一个进程,我正在运行...,pid:" << getpid() <<std::endl;
        sleep(1);
    }
    return 0;
}

效果演示:

其次,除了上述终止进程的方法之外,还可以使用【ctrl+\】

【解释说明】

  • 而这里的【ctrl+\】其实就是 3 号信号所属,我也可以给大家验证一哈(同样的让3号信号执行我们自定义的方法)

效果演示:


(四)信号的概念

综上所述,信号是进程之间事件异步通知的一种方式,属于软中断

理解信号是软中断需要考虑计算机系统中的中断和信号两个概念。

中断:

  • 中断是计算机系统中的一种机制,用于处理与正常执行流程无关的事件。这些事件可能来自硬件,例如硬件故障、定时器到期、输入设备的输入等。当系统接收到中断信号时,当前执行的程序会被中断,系统会转而执行相应的中断处理程序。中断可以是硬中断(由硬件触发)或软中断(由软件触发)。

信号是软中断:

  • 信号是一种用于在软件层面通知进程发生了某个事件的机制。这些事件可以是来自其他进程的通知、异常情况、用户的交互等。当系统检测到某个事件时,会向相应的进程发送一个信号。进程可以事先定义信号的处理方式,比如忽略、捕获、或执行默认操作。

因此综合起来,将信号称为软中断是因为它类似于硬中断的概念,但它是在软件层面实现的。信号提供了一种轻量级的通信和事件处理机制,允许进程在运行时响应各种事件,而不需要像硬中断那样涉及到硬件层面的处理。


(五)小结

  • 每个信号都有一个唯一的编号。常见的信号有诸如SIGKILL(终止进程)、SIGTERM(终止进程,但可被捕获和忽略)等。
  • 进程可以对不同的信号设置不同的处理方式,包括:
  • 默认操作: 操作系统默认对信号执行的动作。
  • 忽略信号: 进程可以选择忽略某个信号。
  • 捕获信号: 进程可以注册一个信号处理函数,以在接收到信号时执行自定义操作。
  • 常见信号:
  • 一些常见的信号包括:
  • SIGINT(2): 由中断字符(通常是Ctrl+C)发送,用于中断正在运行的程序。
  • SIGTERM(15): 用于请求进程正常终止。
  • SIGKILL(9): 用于强制终止进程。
  • SIGHUP(1): 表示终端挂起或控制进程终止。

以上便是本期信号概念的基本介绍。下期我将给大家介绍“信号的产生”相关知识!!!

相关文章
|
4天前
|
Ubuntu Linux
【Linux】详解信号产生的方式
【Linux】详解信号产生的方式
|
4天前
|
监控 Shell Linux
【Shell 命令集合 系统管理 】⭐⭐⭐Linux 向进程发送信号 kill命令 使用指南
【Shell 命令集合 系统管理 】⭐⭐⭐Linux 向进程发送信号 kill命令 使用指南
34 0
|
4天前
|
Unix Linux
【Linux】详解信号的分类&&如何自定义信号的作用
【Linux】详解信号的分类&&如何自定义信号的作用
|
4天前
|
Unix Linux C语言
|
4天前
|
安全 Linux
【Linux】详解用户态和内核态&&内核中信号被处理的时机&&sigaction信号自定义处理方法
【Linux】详解用户态和内核态&&内核中信号被处理的时机&&sigaction信号自定义处理方法
|
4天前
|
存储 Linux C++
【Linux】详解信号的保存&&信号屏蔽字的设置
【Linux】详解信号的保存&&信号屏蔽字的设置
|
4天前
|
存储 Linux
【Linux】对信号产生的内核级理解
【Linux】对信号产生的内核级理解
|
4天前
|
存储 安全 Linux
【探索Linux】P.18(进程信号 —— 信号捕捉 | 信号处理 | sigaction() )
【探索Linux】P.18(进程信号 —— 信号捕捉 | 信号处理 | sigaction() )
9 0
|
4天前
|
存储 算法 Linux
【探索Linux】P.17(进程信号 —— 信号保存 | 阻塞信号 | sigprocmask() | sigpending() )
【探索Linux】P.17(进程信号 —— 信号保存 | 阻塞信号 | sigprocmask() | sigpending() )
12 0
|
4天前
|
算法 Linux C++
【探索Linux】P.16(进程信号 —— 信号产生 | 信号发送 | 核心转储)
【探索Linux】P.16(进程信号 —— 信号产生 | 信号发送 | 核心转储)
8 0