【Linux系统编程】:信号(1)——前置知识,了解信号

1.进程与信号的关系

Unix信号是一种用于Unix信号是一种用于进程间通信的异步通知机制,用于通知进程某个事件已经发生,例如进程终止、中断等。
https://en.wikipedia.org/wiki/Signal_(IPC)

这说明进程需要识别+处理信号 ,但在接收到信号前,进程就应该知道该怎么处理信号,所以进程的信号处理机制应该属于信号的内置功能 ,在接收到信号后,进程会在合适的时间处理该信号,在"接收到处理"的这一时间段中,进程需要保存信号

2.信号的预备知识

2.1 了解前台进程和后台进程

我们之前运行可执行文件,

都是在前台运行,如果我们在程序名后加上取地址(&),该进程就会在后台运行。

前台运行和后台运行有什么区别呢?(注意:程序是静态的,执行程序,一般就会创建进行)

我们可以用ctrl+c中断前台进程的运行,但中断不了后台进程。

这是因为后台进程不与用户直接交互,只有前台进程才会通过图形用户界面(GUI)或命令行界面(CLI)与用户进行交互,响应用户的输入和指令,且一个终端(会话/控制台窗口)一般只会有一个前台进程,可以有多个后台进程。

  • 前台程序通常指的是与用户直接交互的应用程序或界面,它负责处理用户的输入和输出。
  • 后台程序(也称为后台进程或服务)是在计算机系统中运行的,但不直接与用户交互的程序。它们通常在用户不知道或不需要直接干预的情况下执行任务。

2.1 Ctrl+C的本质

那么为什么ctrl+c可以中断前台进程呢?

因为键盘输入ctrl+c会被转换为前台进程识别的2号信号SIGINT,SIGINT信号的默认行为是终止自己。我们可以查看一下所有信号(本质上都是宏),一共62个。(没有32、33)

为什么进程收到2号信号SIGINT就会终断自己呢?

一般而言,进程收到信号有三类处理方式:

注意:自定义动作就是提供一个信号处理函数,要求内核在处理该信号时切换到用户态执行这个处理函数,这种方式称为信号的捕捉(Catch)。

SIGINT的默认动作就是终止自己。

我们可以编写程序验证一下,进程是因为收到信号2才退出的。

我们先认识一下signal函数,

在 C 语言中,signal() 函数用于设置一个信号处理程序,当指定的信号发生时,操作系统会调用这个信号处理程序来处理该信号。

  • 参数:
    • signum:要处理的信号编号(或者宏,SIGINT本质上是一个宏,其值就是2)。例如,SIGINT 表示用户中断信号(通常是 Ctrl+C),SIGSEGV 表示段错误信号,等等。
    • handler:这是一个指向信号处理函数的指针,或者可以是两个特殊的宏 SIG_IGN(忽略信号)和 SIG_DFL(采用默认的信号处理行为)。
      注意:函数指针
  • 返回值
    • 成功时,返回之前的信号处理程序(即旧的信号处理程序)。
    • 失败时,返回 SIG_ERR,并设置 errno 以指示错误原因。
      所以我们可以编写一个函数(自定义接收到SIGINT后进程的处理方式),用来替代SIGINT原来的默认行为(终止进程),当我们运行程序后,按下Ctrl+C,程序没有终止而是执行了我们编写函数的内容,就代表"SIGINT的默认行为确实是终止进程"。
cpp 复制代码
#include <iostream>
#include <unistd.h>
#include <signal.h>
using namespace std;

//signo表示默认行为(旧的)
//函数体表示自定义的行为(新的)
void myhandler(int signo)
{
    cout << "catch signal " << signo << endl;
}
int main()
{
    signal(SIGINT, myhandler);//也可以用2替代SIGINT
    while(true)
    {
        cout << "hello world" << endl;
        sleep(1); 
    }
    return 0;
}

运行结果:

验证无误。

可是这样我们就无法用"Ctrl+C"终止当前进程了,我们可以用"kill -9"杀掉这个进程,也可以在myhandler函数体中,加上进程退出语句exit(1),

这样输入一次Ctrl+C后,进程就会退出。

2.3 Ctrl+C如何变成信号的

Ctrl+C 组合键在 Linux 和其他类 Unix 系统中被用来发送一个特定的信号给正在运行的前台进程,这个信号通常被称为 SIGINT(中断信号)。以下是 Ctrl+C 如何变成信号并影响前台进程的详细过程:

1. 用户输入

  • 当用户在终端或命令行界面中按下 Ctrl+C 组合键时,这是一个明确的用户操作,表示希望中断当前正在运行的前台进程。

2. 终端程序捕获

  • 终端程序(如 bash、zsh 等 shell)会捕获这个按键组合。终端程序是用户与操作系统内核之间的一个接口,它负责接收用户的输入并将其转换为相应的操作或命令。

3. 发送信号给前台进程

  • 终端程序识别到 Ctrl+C 后,会生成一个 SIGINT 信号,并将其发送给当前正在运行的前台进程。前台进程是指当前在终端中运行且与用户交互的进程。

4. 内核处理信号

  • 操作系统内核接收到终端程序发送的信号后,会将其传递给目标前台进程。内核是操作系统的核心部分,负责管理硬件、内存、进程等系统资源。

5. 进程处理信号

  • 前台进程收到 SIGINT 信号后,会根据信号的默认处理方式或自定义处理方式来做出相应的响应。
    • 默认处理方式:大多数情况下,SIGINT 信号的默认处理方式是终止进程的执行。也就是说,如果进程没有捕获或忽略这个信号,那么它会被终止。
    • 自定义处理方式:有些程序可能会捕获 SIGINT 信号,并进行自定义的处理,比如保存数据、释放资源等,然后再退出。这通常是通过在程序中注册一个信号处理函数来实现的。

6. 进程终止或继续

  • 根据进程对 SIGINT 信号的处理方式,进程可能会被终止,也可能会继续执行(如果它捕获了信号并进行了自定义处理)。

注意事项

  • Ctrl+C 发送的 SIGINT 信号是前台进程组信号,这意味着如果当前有多个进程组成了一个前台进程组,那么它们都会收到这个信号。
  • 除了 SIGINT 外,Linux 系统中还有许多其他信号,如 SIGKILL(强制终止进程)、SIGTERM(请求终止进程)等,它们都可以通过不同的方式发送给进程,以实现对进程的控制和管理。
  • 前台进程在运行过程中用户随时可能按下Ctrl-C而产生一个信号,也就是说该进程的用户空间代码执行到任何地方都有可能收到SIGINT信号而终止,所以信号相对于进程的控制流程来说是异步(Asynchronous)

来源:https://yiyan.baidu.com/

可参考
linux信号| 学习信号四步走 | 学习信号需要打通哪些知识脉络?
键盘输入流程

3.不是所有的信号都可以被signal()捕捉

3.1捕捉信号3(SIGQUIT)

我们用signal()来捕捉3号信号,

cpp 复制代码
#include <iostream>
#include <unistd.h>
#include <signal.h>
using namespace std;

void myhandler(int signo)
{
    cout << "catch signal " << signo << endl;
}
int main()
{
    signal(3, myhandler);
    while(true)
    {
        cout << "hello world" << endl;
        sleep(1); 
    }

    return 0;
}

重新编译并运行,

但我们向进程myprocess发送3号信号时,

旧的默认行为被替换成打印"catch signal:3",

3.2 捕捉信号19(SIGSTOP)

将上面代码中

cpp 复制代码
    signal(3, myhandler);

改成

cpp 复制代码
    signal(19, myhandler);

重新编译并运行,

向该程序发送19号信号后,进程直接终止,说明19号信号没有被signal捕获。

我们可以写一个循环,按照上面的方法一一测试所有的信号是否能被捕捉。

前31个信号中,只有9号信号和19号信号无法被捕捉。

相关推荐
chenbin52016 分钟前
Jenkins 自动构建Job
运维·jenkins
java 凯17 分钟前
Jenkins插件管理切换国内源地址
运维·jenkins
AI服务老曹21 分钟前
运用先进的智能算法和优化模型,进行科学合理调度的智慧园区开源了
运维·人工智能·安全·开源·音视频
风静如云1 小时前
OpenBMC:BmcWeb定义service
linux
sszdzq2 小时前
Docker
运维·docker·容器
book01212 小时前
MySql数据库运维学习笔记
运维·数据库·mysql
leoufung2 小时前
VIM FZF 安裝和使用
linux·编辑器·vim
bugtraq20213 小时前
XiaoMi Mi5(gemini) 刷入Ubuntu Touch 16.04——安卓手机刷入Linux
linux·运维·ubuntu
xmweisi3 小时前
【华为】报文统计的技术NetStream
运维·服务器·网络·华为认证
VVVVWeiYee3 小时前
BGP配置华为——路径优选验证
运维·网络·华为·信息与通信