【探索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.mzph.cn/news/169336.shtml

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

相关文章

ZC-OFDM模糊函数原理及仿真

文章目录 前言一、ZC 序列二、ZC-OFDM 信号1、OFDM 信号表达式2、模糊函数表达式三、MATLAB 仿真1、MATLAB 核心源码2、仿真结果①、ZC-OFDM 模糊函数②、ZC-OFDM 距离分辨率③、ZC-OFDM 速度分辨率前言 本文进行 ZC-OFDM 的原理讲解及仿真,首先看一下 ZC-OFDM 的模糊函数仿真…

【持续更新】汇总了一份前端领域必看面试题

文章目录 1. 写在前面2. 前端面试汇总2.0.1. 如何提⾼webpack的打包速度2.0.2. 数组去重2.0.3. 前端有几种缓存方式&#xff1f;2.0.4. nextTick描述一下&#xff1f;2.0.5. Webpack层面的优化&#xff1f;2.0.6. 代码层面的优化&#xff1f;2.0.7. Web 技术的优化&#xff1f;…

【C++】PACS医学图像存储和传输系统源码带三维重建

PACS&#xff08;Picture Archiving and Communication System&#xff09;系统作为医学图像的存储和传输平台&#xff0c;为医生和患者提供了便捷高效的诊疗服务支持。近年来&#xff0c;三维重建技术在PACS系统中的应用越来越广泛。 三维后处理功能是临床数字技术中的重要组成…

【Linux】Linux权限管理

目录 一、Linux中权限的概念 二、 Linux下的用户 2.1 用户的类型 2.2 用户创建、切换和删除 2.2.1 useradd或adduser命令创建用户 2.2.2 passwd命令设置用户密码 2.2.3 userdel命令删除用户 2.2.4 su命令切换用户身份等来管理和操作用户 2.3 注意事项 三、权限的管理…

浅析基于物联网的远程抄表系统的设计及应用

安科瑞 华楠 摘 要&#xff1a;本文基于物联网的概念&#xff0c;使用 ZigBee、通用分组无线服务技术两种无线通信技术相结合的方式实现远程抄表并对数据进行存储和管理。此系统设计主要分为硬件方面的设计和软件方面的设计&#xff0c;硬件方面的设计需要完成三个部分的硬件制…

redis运维(二十)redis 的扩展应用 lua(二)

一 redis 的扩展应用 lua redis lua脚本语法 ① 什么是脚本缓存 redis 缓存lua脚本 说明&#xff1a; 重启redis,脚本缓存会丢失 下面讲解 SCRIPT ... 系列 SCRIPT ② LOAD 语法&#xff1a;SCRIPT LOAD lua代码 -->载入一个脚本,只是预加载,不执行思考1&#xff1…

Vue解析器

解析器本质上是一个状态机。但我们也曾提到&#xff0c;正则表达式其实也是一个状态机。因此在编写 parser 的时候&#xff0c;利用正则表达式能够让我们少写不少代码。本章我们将更多地利用正则表达式来实现 HTML 解析器。另外&#xff0c;一个完善的 HTML 解析器远比想象的要…

PyQt基础_004_ 按钮类控件QPushButton以及自定义按钮控件

Qpushbutton基本操作 1.热键 2.按钮加图标 3.按钮事件等 import sys from PyQt5.QtCore import * from PyQt5.QtGui import * from PyQt5.QtWidgets import *class Form(QDialog):def __init__(self, parentNone):super(Form, self).__init__(parent)layout QVBoxLayout()se…

Android 打包aar包含第三方aar 解决方案

Android 打包aar包含第三方aar 因项目需要&#xff0c;打包aar包含第三方aar&#xff0c;如果直接对module进行打包会产生一些问题。 * What went wrong: Direct local .aar file dependencies are not supported when building an AAR. The resulting AAR would be broken be…

如何将Postman API转换JMeter进行扩展

可扩展性 Postman测试无法扩展。如果您的集合中有很多请求&#xff0c;Postman / Newman将使用1个线程&#xff08;用户&#xff09;并按顺序执行这些请求&#xff0c;而不是使用多个线程并发执行。 性能测试能力 由于可扩展性限制&#xff0c;Postman不适合API性能测试。性…

力扣二叉树--总结篇(1)

前言 七天写了二十道题&#xff0c;前面感觉不错&#xff0c;后面越来越写不出来&#xff0c;刷题的心境和效果已然发生了变化。写个阶段总结&#xff0c;及时调整。 内容 先是二叉树的遍历 前序&#xff0c;中序&#xff0c;后序&#xff0c;即对应的递归&#xff0c;迭代…

visual studio 下的git

我这个是看视频笔记 YouTube : https://www.youtube.com/watch?vgkDASVE_Hdg 主要内容是&#xff1a;建立git 库&#xff0c; 保存commit&#xff0c; 建立分支 create branch, 合并分支merge branch,比较 diff&#xff0c;Revert ,history,delete branch, rename branch, t…

金融众筹模式系统源码 适合创业孵化机构+天使投资机构+投资基金会等 附带完整的搭建教程

随着互联网技术的发展和金融市场的开放&#xff0c;金融众筹模式逐渐成为一种新型的融资方式。这种模式通过互联网平台聚集大量投资者&#xff0c;共同参与到一个项目中&#xff0c;为项目提供资金支持&#xff0c;最终获得投资回报。今天罗峰给大家分享一款金融众筹模式系统源…

基于springboot实现学生成绩管理系统项目【项目源码+论文说明】

基于springboot实现学生成绩管理系统演示 摘要 随着信息技术和网络技术的飞速发展&#xff0c;人类已进入全新信息化时代&#xff0c;传统管理技术已无法高效&#xff0c;便捷地管理信息。为了迎合时代需求&#xff0c;优化管理效率&#xff0c;各种各样的管理系统应运而生&am…

Spring框架学习 -- Bean的生命周期和作用域

目录 前言 案例 案例分析 作用域的定义 Bean对象的6种作用域 Singleton prototype 设置作用域 ​编辑延迟初始化 Spring的执行流程 Bean的生命周期 前言 我们可以类比一下普通变量的生命周期和作用域, 大多数变量的生命周期和作用域都被限定在了花括号内 {}, 除…

微信公众号快速接入大模型

今天找到一个可以快速将大模型接入公众号的方法&#xff0c;现在跟大家分享一下。 如何让微信公众号接入大模型文案创作能力&#xff0c;实现类似ChatGPT文案创作功能。方法其实很简单&#xff0c;只需打开地址“http://www.botaigc.cn:8900/mpauth”&#xff0c;用微信扫码即可…

根据商品ID获取淘宝数据接口|淘宝商品详情接口|淘宝关键词搜索商品列表接口|淘宝到手价接口|淘宝API接口

淘宝API接口可以运用到多种业务场景中&#xff0c;以下列举了一些主要的场景&#xff1a; 商品信息展示&#xff1a;通过调用淘宝API详情接口&#xff0c;可以获取商品的详细信息&#xff0c;如商品标题、价格、库存、销量、评价等数据。这些信息可以用于在自己的网站或应用程…

实时LCM的ImgPilot搭建部署

ImgPilot是具有实时潜在一致性模型&#xff08;LCM&#xff09;功能的图像试点 下载源码 GitHub - leptonai/imgpilot: Image pilot with the power of Real-Time Latent Consistency Modelhttps://github.com/leptonai/imgpilot安装前端web cd imgpilot npm install 安装…

C++初阶 | [六] 模板初阶

摘要&#xff1a;泛型编程&#xff0c;函数模板&#xff0c;类模板 使用函数重载虽然可以实现&#xff0c;但是有一下几个不好的地方&#xff1a; 重载的函数仅仅是类型不同&#xff0c;代码复用率比较低&#xff0c;只要有新类型出现时&#xff0c;就需要用户自己增加对应的函…

新手如何买卖基金,基金投资基础入门

一、教程描述 本套基金教程&#xff0c;大小2.50G&#xff0c;共有13个文件。 二、教程目录 第01课&#xff1a;基金入门&#xff0c;学会投资其实不难.mp4 第02课&#xff1a;基金分类&#xff0c;琳琅满目清清楚楚.mp4 第03课&#xff1a;以稳取胜&#xff0c;稳健基金稳…