【从浅学到熟知Linux】信号机制上篇=>信号的概念与产生方式(含signal/raise/abort函数使用示例、core dump核心转储、软件与硬件异常信号详解)

本文详细介绍了Linux系统中的信号概念,包括信号的产生方式(如终端按键、系统调用)、信号示例(如Ctrl+C、Ctrl+Z)、信号的识别与处理,以及如何通过kill、raise和abort等函数发送和捕获信号。还探讨了核心转储(coredump)和不同信号的触发条件,如硬件异常引发的SIGFPE和SIGSEGV。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

在这里插入图片描述

🏠关于专栏:Linux的浅学到熟知专栏用于记录Linux系统编程、网络编程等内容。
🎯每天努力一点点,技术变化看得见


生活中的信号

在讨论Linux中的信号前,我们一起回想一下生活中的信号。生活中存在大量的信号,如下课铃、红绿灯、发令枪、闹钟、外卖电话…当我们看到红灯,就会停下来等待;当我们听到下课铃就知道下课时间到了;当我们听到起床闹铃,就知道该起床洗漱了…

a. 我们是怎么认识这些信号的呢?有人教我们认识这些信号,并且告诉我们处理这些信号的方法;
b. 即使是我们现在没有信号产生,我也知道信号产生之后,我应该干什么;
c. 信号产生了,我们可能并不立即处理这个信号,在合适的时候,因为我们可能正在做更重要的事情。

【例子】小明买了个零食快递

Ⅰ 小明买了一个零食快递,虽然快递还没有到达,但小明已经知道快递到达时,他已经知道什么是快递,他能够认识快递。也就是说,在快递信号到达前,小明已经具备信号的识别能力

Ⅱ 当快递到达时,快递小哥给小明打了个电话,小明正在推对方的王者高地,他选择在他打完这局后再取快递,同时他记得他打完这局后要处理这个信号。也就是说,小明收到信号不一定要马上处理信号,可以选择合适的时候再处理信号,但处理信号前,需要保存信号

Ⅲ 小明取到快递后,对于这个快递的处理方式有三种:①直接开心的打开(默认动作)②送给他的女朋友翠花(自定义动作)③直接将快递放在杂物间(忽略);

同理,Linux系统中的进程需要具备如下能力:

  1. 进程必须能够识别+处理信号(信号的识别和处理能力,属于进程内置的);
  2. 进程即使没有收到信号,也能知道哪些信号该怎么处理;
  3. 进程真的收到了一个具体的信号的时候,进程可能不会立即处理这个信号,而是在合适的时候;
  4. 在进程收到信号,到信号开始被处理,一定会存在一个窗口期,进程具有临时保存哪些信号已经发生了的能力。

★ps:进程处理信号的方式有三种:①默认动作;②自定义动作;③忽略

Linux中的信号

信号示例及概念

那Linux中哪里存在信号呢?当我们按下热键ctrl+C为什么能够杀死我们当前bash中在运行的前台进程呢?

用户按下ctrl+C这个热键组合时,本质是:产生了一个硬件中断,该硬件中断被操作系统获取并解释成了信号,发送给了目标前台进程。进程收到该信号后,执行该信号的内置默认动作——终止进程。

★ps:Linux中,一次登陆会启动一个终端,一个终端一般会配置一个bash。每个bash中只允许一个进程是前台进程,并允许多个后台进程。前台进程和后台进程的区别在于:能否接收键盘的输入(前台进程能够接收键盘数据)。我们执行一个程序./process默认是前台进程,但如果以./process &方式执行,则为后台进程。

★ps:前台进程在运行过程中,用户随时可能按下ctrl+C而产生一个信号,也就是说该进程的用户空间代码指定到任何地方都可能收到2号SIGINT信号而终止。所以进程收到信号相对于进程的控制流程是异步,意味着进程无法控制信号何时到达。

★ps:信号到达时应及时进行处理,以保证系统的正确性和稳定性。

由此,我们可以得到信号的概念:信号是进程之间事件异步通知的一种方式,属于软中断。(我们学习的信号就是用软件方式,对进程硬件中断的模拟)。

查看各种信号

如果需要查看系统定义的信号列表,可以使用如下命令↓↓↓

kill-l

在这里插入图片描述
上图中,1到31号信号属于普通信号,编号34及以上的信号属于实时信号,对于实时信号这里不做讨论。这些信号在signal.h中均有定义,例如2号信号定义为#define SIGINT 2

对于每个信号,系统都有内置默认的处理动作,我们可以通过man 7 signal来查看↓↓↓
在这里插入图片描述

初始信号的捕捉

系统中对于信号可以选择3种处理方式:忽略、执行该信号的默认动作及自定义动作。各个信号在用户没有指定的情况下,都是执行默认动作的。那如何忽略和自定义呢?

操作系统提供了一个自定义信号处理方式的函数,要求内核在处理对应信号时,切换到用户态执行这个处理函数(或直接忽略),这种方式称为捕捉一个信号。↓↓↓
在这里插入图片描述
第一个参数signum是信号的编号(kill -l可以列出所有信号编号),第二个参数handler的类型是sighandler_t,这个类型是一个返回值为void,参数列表需要传入一个int参数的函数指针类型。第二个参数我们可以将其设置为SIG_DFL,表示执行系统默认操作;设置为SIG_IGN表示忽略改信号。

上面讲述到,ctrl+C组合热键是给当前前台进程发送2号信号,下面代码使用signal捕捉了2号信号,如果当前进程收到2号进程,则会执行Handler函数↓↓↓

#include <stdio.h>
#include <unistd.h>
#include <signal.h>

void Handler(int signo)
{
   
	printf("I have recieve a signo = %d\n",signo);
	sleep(1);
}

int main()
{
   
	signal(2, Handler);
	while(1)
	{
   
		printf("I am running...\n");
		sleep(1);
	}
	return 0;
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值