【探索Linux】—— 强大的命令行工具 P.16(进程信号 —— 信号产生 | 信号发送 | 核心转储)

在这里插入图片描述

阅读导航

  • 引言
  • 一、概念
    • (1)基本概念
    • (2)kill -l命令(察看系统定义的信号列表)
  • 二、产生信号
    • (1)通过终端按键产生信号
      • -- 信号产生
      • -- Core Dump(核心转储)
    • (2)调用系统函数向进程发信号
      • kill( ) 函数
      • abort( ) 函数
    • (3) 由软件条件产生信号
      • alarm( ) 函数
    • (4)硬件异常产生信号
  • 温馨提示

引言

在现代社会中,信号无处不在。我们的生活充满了各种各样的信号,它们指引着我们前进的方向,使我们能够了解周围环境的变化。正如在计算机编程中一样,Linux进程信号也是一种重要的信号,它们扮演着相似的角色。

想象一下,在繁忙的城市街道上行驶,交通信号灯是我们最熟悉的信号之一。当红灯亮起时,我们知道需要停下来等待;而绿灯的出现则意味着可以继续前行。这些信号通过明确的方式向司机传达信息,确保道路上的交通有序进行。

类似地,Linux进程信号也是一种用于进程间通信和控制的手段。它们是操作系统通过发送特定信号给进程来通知其发生了某种事件或请求进行某种操作的机制。这些信号可以用于中断进程、终止进程、重新启动进程以及执行其他与进程相关的操作

Linux进程信号的产生和发送是一个复杂而精密的过程,它涉及操作系统内部的多个组件和机制。深入理解信号的工作原理对于编写高效、稳定的程序至关重要。通过掌握信号的概念和使用方法,我们可以更好地利用操作系统提供的功能,实现各种任务的灵活管理和交互。

在本文中,我们将探讨Linux进程信号的基本概念、信号的产生方式以及如何通过编程发送信号给进程。通过深入了解信号的工作原理,我们将能够更好地理解操作系统的内部机制,并在编写程序时更加灵活地利用信号来实现我们的目标。让我们一起踏上这个关于Linux进程信号的精彩探索之旅吧!

一、概念

(1)基本概念

Linux中的信号是一种软件中断。当操作系统发送一个信号给一个进程时,该进程会立即停止正在执行的任务,并跳转到一个特定的信号处理函数中进行处理。信号可以用于中断进程、终止进程、重新启动进程以及执行其他与进程相关的操作。

(2)kill -l命令(察看系统定义的信号列表)

在这里插入图片描述
Linux中共有64个不同的信号,它们被分为两类:标准信号和实时信号。标准信号的编号从1到31,实时信号的编号从32到64。每个信号都有一个唯一的名称和一个对应的数字编号,例如SIGINT表示中断信号,其编号为2。

在 Linux 中,这些宏定义通常可以在 <signal.h> 头文件中找到。每个信号都有一个编号和一个宏定义名称。

对于信号的产生条件和默认处理动作的详细说明,可以通过查看 signal(7) 的手册页来获取。可以使用以下命令来查看:

man 7 signal

这将打开关于信号的手册页,其中包含了关于信号产生条件、默认处理动作以及如何使用 signal() 函数进行自定义信号处理的详细说明。
在这里插入图片描述
在Linux中,我们可以通过编写信号处理函数来对信号进行处理。信号处理函数是在接收到信号后自动调用的函数,用于处理信号并执行相应的操作。当一个信号产生时,操作系统通常会暂停当前进程的执行,保存进程的状态,然后跳转到信号处理函数中执行相应的操作。

二、产生信号

Linux中的信号可以由以下三种方式产生

  1. 用户按下终端键(如Ctrl+C),操作系统会将一个SIGINT信号发送给前台进程组中的所有进程;

  2. 进程调用kill()系统调用,向指定进程或进程组发送信号;

  3. 操作系统本身发现了某些异常情况,如进程访问非法内存地址、除零错误等,就会向进程发送相应的信号。

(1)通过终端按键产生信号

– 信号产生

在终端中,你可以通过按下特定的组合键来向正在运行的程序发送信号。其中最常用的是以下几个:

  1. Ctrl+C:产生 SIGINT 信号,通常用于中断当前程序的执行。
  2. Ctrl+Z:产生 SIGTSTP 信号,通常用于挂起当前程序的执行。
  3. Ctrl+\:产生 SIGQUIT 信号,通常用于请求当前程序退出,并生成 core 文件。

通过在终端中按下这些组合键,你可以模拟产生这些信号,从而触发相应的信号处理动作。

– Core Dump(核心转储)

Core Dump(核心转储)是指在程序异常终止时,将程序的内存状态转储到一个特殊文件中。这个文件称为 core 文件,它包含了程序在崩溃前的内存映像。

当程序发生严重错误、段错误(Segmentation Fault)或其他类似的问题导致程序崩溃时,操作系统会生成一个 core 文件。这个文件可以被用于调试程序,通过分析 core 文件可以了解程序崩溃时的内存状态,有助于定位和修复错误。

core 文件的生成受到操作系统的控制,通常在以下情况下会生成 core 文件:

  1. 程序显式地调用 abort() 函数。
  2. 程序收到 SIGQUIT 或 SIGILL 等信号。
  3. 程序发生段错误(Segmentation Fault)。

默认情况下,core 文件的生成是被启用的。但是,有时可能已经被禁用或限制了大小。你可以使用以下命令来检查系统的 core 文件配置:

ulimit -a | grep core

在这里插入图片描述

如果输出中显示了 core file size,则表示 core 文件生成是启用的,并且会显示 core 文件的最大大小限制。

(2)调用系统函数向进程发信号

kill( ) 函数

要向进程发送信号,可以使用系统函数kill()kill()函数的原型如下:

#include <sys/types.h>
#include <signal.h>int kill(pid_t pid, int sig);

其中,pid参数是目标进程的进程ID(PID),sig参数是要发送的信号编号。

以下是一个示例代码,演示如何使用kill()函数向进程发送信号:

#include <sys/types.h>
#include <signal.h>
#include <stdio.h>int main() {pid_t pid = 1234; // 替换为目标进程的实际进程IDif (kill(pid, SIGINT) == 0) {printf("成功发送信号给进程 %d\n", pid);} else {perror("发送信号失败");}return 0;
}

在上面的示例中,kill()函数用来向进程ID为pid的进程发送SIGINT信号(中断信号)。如果函数返回值为0,则表示成功发送信号。否则,可以使用perror()函数输出错误信息。

abort( ) 函数

abort()是一个C标准库函数,用于引发程序的异常终止。调用abort()函数会导致程序生成core文件(如果core文件生成被启用)并退出。abort()函数的原型如下:

#include <stdlib.h>void abort(void);

abort()函数会向进程发送SIGABRT信号,这是一个特殊的终止信号,通常用于表示程序遇到了严重错误,并主动请求终止。

当调用abort()函数时,系统会进行一系列的处理操作,包括终止当前进程、生成core文件、关闭文件等。然后,程序将立即退出。

以下是一个示例代码,演示了如何使用abort()函数:

#include <stdio.h>
#include <stdlib.h>int main() {printf("开始执行程序\n");// 模拟一个错误条件int divisor = 0;if (divisor == 0) {printf("除数为零,程序终止\n");abort();}// 正常执行的代码printf("正常执行的代码\n");return 0;
}

在上面的示例中,当除数为零时,程序调用了abort()函数导致程序异常终止。在这种情况下,将会输出"除数为零,程序终止",然后程序会生成core文件(如果core文件生成被启用)并退出。

(3) 由软件条件产生信号

在Linux中,由软件条件产生信号是通过使用信号处理函数来实现的。信号是一种软件中断,用于通知进程发生了某个事件。下面是一个简单的示例代码,展示了如何在Linux中由软件条件产生信号:

#include <stdio.h>
#include <unistd.h>
#include <signal.h>void signal_handler(int signal_num) {printf("Received signal: %d\n", signal_num);
}int main() {// 注册信号处理函数signal(SIGUSR1, signal_handler);printf("Waiting for signal...\n");sleep(10);  // 模拟程序执行的一段时间return 0;
}

在上面的示例中,首先使用signal函数注册了一个信号处理函数signal_handler,该函数会在接收到SIGUSR1信号时被调用。然后,程序进入休眠状态sleep(10),等待信号的到来。可以使用以下命令发送SIGUSR1信号给该程序:

$ kill -SIGUSR1 <pid>

其中,<pid>是运行该程序的进程ID。当程序接收到信号后,就会执行信号处理函数,并打印出接收到的信号编号。

alarm( ) 函数

在Linux中,alarm()函数可以用来设置一个定时器,当定时器到时后,会给进程发送一个SIGALRM信号。alarm()函数的原型如下:

unsigned int alarm(unsigned int seconds);

其中,seconds参数指定了定时器的时间,单位是秒。如果seconds为0,则会取消之前设置的定时器。

以下是一个简单的示例代码,展示了如何使用alarm()函数来实现定时器功能:

#include <stdio.h>
#include <unistd.h>
#include <signal.h>void signal_handler(int signal_num) {printf("Received signal: %d\n", signal_num);
}int main() {// 注册信号处理函数signal(SIGALRM, signal_handler);// 设置定时器,时间为5秒alarm(5);printf("Waiting for alarm...\n");pause();  // 等待信号的到来return 0;
}

在上面的代码中,首先注册了一个信号处理函数signal_handler,当接收到SIGALRM信号时就会执行该函数。然后使用alarm()函数设置定时器,时间为5秒。接着,程序进入休眠状态pause(),等待信号的到来。可以看到,在5秒后,程序会收到SIGALRM信号,并执行对应的信号处理函数。

需要注意的是,alarm()函数只能设置一个全局定时器,如果需要同时多个定时器,可以考虑使用setitimer()函数。此外,调用alarm()函数会取消之前设置的定时器,如果需要保留之前的定时器,可以使用setitimer()ITIMER_VIRTUALITIMER_REAL选项。

(4)硬件异常产生信号

在Linux中,硬件异常通常由操作系统内核检测到,并通过信号来通知相关进程。下面是一些常见的硬件异常和相应的信号:

  1. 除零异常(Divide-by-Zero):当执行除法操作时除数为零时触发的异常。操作系统会向进程发送SIGFPE信号,表示浮点异常。

  2. 非法指令异常(Illegal Instruction):当执行非法或无效的指令时触发的异常。操作系统会向进程发送SIGILL信号,表示非法指令。

  3. 段错误异常(Segmentation Fault):当进程访问了未分配给它的内存空间或者试图向只读内存写入数据时触发的异常。操作系统会向进程发送SIGSEGV信号,表示段错误。

  4. 总线错误异常(Bus Error):当进程试图访问非法的物理内存地址或者对不支持的对齐方式进行访问时触发的异常。操作系统会向进程发送SIGBUS信号,表示总线错误。

  5. 浮点异常(Floating-Point Exception):当执行浮点计算出现溢出、下溢或非法操作时触发的异常。操作系统会向进程发送SIGFPE信号,表示浮点异常。

这些硬件异常信号可以被进程捕获并进行相应的处理。通过设置信号处理函数,进程可以在收到硬件异常信号时采取适当的措施,如记录日志、恢复状态或退出程序等。

🚨注意硬件异常的处理通常是由操作系统内核负责的,应用程序通常无法直接控制硬件异常的触发和处理。应用程序可以通过注册信号处理函数来处理与硬件异常相关的信号,但具体的处理方式受限于操作系统和硬件平台的约束

温馨提示

感谢您对博主文章的关注与支持!如果您喜欢这篇文章,可以点赞、评论和分享给您的同学,这将对我提供巨大的鼓励和支持。另外,我计划在未来的更新中持续探讨与本文相关的内容。我会为您带来更多关于Linux以及C++编程技术问题的深入解析、应用案例和趣味玩法等。如果感兴趣的话可以关注博主的更新,不要错过任何精彩内容!

再次感谢您的支持和关注。我们期待与您建立更紧密的互动,共同探索Linux、C++、算法和编程的奥秘。祝您生活愉快,排便顺畅!
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/217396.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

量子计算的发展

目录 一、量子力学的发展历程二、量子计算的发展历程三、量子计算机的发展历程四、量子信息科学的发展 一、量子力学的发展历程 量子力学是现代物理学的一个基本分支&#xff0c;它的发展始于20世纪初。以下是量子力学发展的几个重要阶段&#xff1a; 普朗克&#xff08;1900&…

分享一个鬼~

前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到网站。 先看效果&#xff1a; 上源码&#xff1a; import GUI from "https://cdn.jsdelivr.net/npm/lil-gui0.18.2/esm"const canv…

二分查找之红蓝二分查找

꒰˃͈꒵˂͈꒱ write in front ꒰˃͈꒵˂͈꒱ ʕ̯•͡˔•̯᷅ʔ大家好&#xff0c;我是xiaoxie.希望你看完之后,有不足之处请多多谅解&#xff0c;让我们一起共同进步૮₍❀ᴗ͈ . ᴗ͈ აxiaoxieʕ̯•͡˔•̯᷅ʔ—CSDN博客 本文由xiaoxieʕ̯•͡˔•̯᷅ʔ 原创 CSDN …

鸿蒙原生应用/元服务开发-AGC分发如何上架HarmonyOS应用

一、上架整体流程 二、上架HarmonyOS应用 获取到HarmonyOS应用软件包后&#xff0c;开发者可将应用提交至AGC申请上架。上架成功后&#xff0c;用户即可在华为应用市场搜索获取开发者的HarmonyOS应用。 配置应用信息 1.登录AppGallery Connect&#xff0c;选择“我的应用”。…

CCC联盟——UWB MAC(二)

在上一篇文章中对CCC联盟UWB MAC框架进行了介绍&#xff0c;在本文中&#xff0c;将MAC层的时间网格进行简单介绍。 2、MAC时间网格&#xff08;Time Grid) DK UWB测距协议属于一对多&#xff08;One to Many, O2M)测距协议。发起者&#xff0c;每次发送4帧&#xff0c;接收N帧…

学习Pandas 二(Pandas缺失值处理、数据离散化、合并、交叉表与透视表、分组与聚合)

文章目录 六、高级处理-缺失值处理6.1 检查是否有缺失值6.2 缺失值处理6.3 不是缺失值NaN&#xff0c;有默认标记的 七、高级处理-数据离散化7.1 什么是数据的离散化7.2 为什么要离散化7.3 如何实现数据的离散化 八、高级处理-合并8.1 pc.concat实现合并&#xff0c;按方向进行…

Linux:Ubuntu虚拟机安装详解:VMware下的逐步指南

目录 1. centOS系统 2. ubuntu系统 1. 下载Ubuntu映像 step1 step2 step3 2. 新建虚拟机 step1 step2 Step3 step4 step5 step6 内存 内核 映像 显示 网络 3. 网络配置 NAT模式 本机IP获取 ​编辑 bridge模式 4. 开启虚拟机 5. 虚拟机常用配置 语言 …

为什么,word文件在只读模式下,仍然能编辑?

Word文档设置了只读模式&#xff0c;是可以编辑的&#xff0c;但是当我们进行保存的时候就会发现&#xff0c;word提示需要重命名并选择新路径才能够保存。 这种操作&#xff0c;即使可以编辑文字&#xff0c;但是原文件是不会受到影响的&#xff0c;编辑之后的word文件会保存到…

Redis Stream消息队列

什么是Stream? Stream 实际上是一个具有消息发布/订阅功能的组件&#xff0c;也就常说的消息队列。其实这种类似于 broker/consumer(生产者/消费者)的数据结构很常见&#xff0c;比如 RabbitMQ 消息中间件、Celery 消息中间件&#xff0c;以及 Kafka 分布式消息系统等&#x…

openEuler20.03学习01-创建虚拟机

赶个时髦&#xff0c;开始学习openEuler 20.03 (LTS-SP3) 操作系统iso下载地址&#xff1a;https://repo.openeuler.openatom.cn/openEuler-20.03-LTS-SP3/ISO/x86_64/openEuler-20.03-LTS-SP3-x86_64-dvd.iso 公司有现成的vmware环境&#xff0c;创建虚拟机i测试&#xff0c…

qgis添加arcgis的mapserver

左侧浏览器-ArcGIS地图服务器-右键-新建连接 Folder: / 展开-双击图层即可

通过ros系统中websocket中发送sensor_msgs::Image数据给web端显示(三)

通过ros系统中websocket中发送sensor_msgs::Image数据给web端显示(三) 不使用base64编码方式传递 #include <ros/ros.h> #include <signal.h> #include <sensor_msgs/Image.h> #include <message_filters/subscriber.h> #include <message_filter…