Linux进程通信之信号

目录

1、Linux中的信号编号及其名字

2、信号的处理:

3、信号的使用

1.入门版

1.信号发送函数kill

示例:

2.信号处理函数的注册signal

示例:

2.高级版

1. 信号处理发送函数sigqueue

示例:

2.信号处理函数的注册sigaction

 示例:

Linux 中信号是一种进程间通信的机制,用于在异步事件发生时通知进程。实际信号是软中断,许多重要的程序都需要处理信号。比如,终端用户输入了 ctrl+c 来中断程序,会通过信号机制停止一个程序。

1、Linux中的信号编号及其名字

具体的信号名称可以使用kill -l来查看信号的名字以及序号,信号是从1开始编号的,不存在0号信号。kill对于信号0有特殊的应用。

这里介绍一些常用的信号

  1. SIGHUP (1): 挂起信号。通常在与终端连接的会话结束时发送给进程。

  2. SIGINT (2): 中断信号。通常由用户在终端按下 Ctrl+C 时生成,用于中断正在运行的程序。

  3. SIGQUIT (3): 退出信号。类似于 SIGINT,但当用户在终端按下 Ctrl+\ 时生成,通常用于生成核心转储文件。

  4. SIGILL (4): 非法指令信号。表示进程尝试执行一个非法的指令,通常是因为程序错误导致的。

  5. SIGTRAP (5): 跟踪/断点陷阱信号。通常由调试器使用,用于实现断点等调试功能。

  6. SIGABRT (6): 中止信号。通常由 abort 函数生成,表示进程发生了严重错误。

  7. SIGFPE (8): 浮点异常信号。表示进程执行了一个无效的浮点操作,例如除以零。

  8. SIGKILL (9): 杀死信号。用于强制终止进程。该信号不能被捕获或忽略。

  9. SIGSEGV (11): 段错误信号。表示进程访问了无效的内存地址,通常是因为编程错误导致的。

  10. SIGPIPE (13): 管道破裂信号。通常在进程尝试向已关闭的管道写入数据时生成。

  11. SIGALRM (14): 定时器超时信号。通常由 alarm 函数生成,表示定时器已过期。

  12. SIGTERM (15): 终止信号。用于请求进程正常终止。进程可以捕获此信号,并执行清理工作后终止。

  13. SIGUSR1 (10): 用户定义信号 1。可以由用户定义为特定用途。

  14. SIGUSR2 (12): 用户定义信号 2。可以由用户定义为特定用途。

  15. SIGCHLD (17): 子进程状态改变信号。通常在子进程退出或停止时生成。

  16. SIGCONT (18): 继续执行信号。通常用于从停止状态继续进程的执行。

  17. SIGSTOP (19): 停止信号。用于暂停进程的执行。与 SIGKILL 不同,SIGSTOP 可以被捕获并处理。

  18. SIGTSTP (20): 终端停止信号。通常由用户在终端按下 Ctrl+Z 时生成,用于暂停正在运行的进程。

  19. SIGTTIN (21): 后台进程尝试读取标准输入时的信号。

  20. SIGTTOU (22): 后台进程尝试写入标准输出时的信号。

2、信号的处理:

信号的处理有三种方法,分别是:忽略、捕捉和默认动作

忽略信号:大多数信号都可以通过将其处理动作设置为 SIG_IGN(表示忽略)来屏蔽,例如

#include <signal.h>
int main() {// 忽略 SIGUSR1 信号signal(SIGUSR1, SIG_IGN);// 进程执行其他任务 return 0;
}

但是,对于 SIGKILLSIGSTOP 两个信号,是不能被忽略的。这是因为它们是系统用于可靠终止和停止进程的方式

捕捉信号:用户可以通过注册一个信号处理函数来捕捉信号。当信号发生时,内核将调用用户定义的函数。

系统默认动作:每个信号都有一个默认的处理动作,通常比较粗暴,例如终止进程。可以通过 man 7 signal 命令查看系统对每个信号的默认处理动作。用户可以选择采用默认动作,也可以通过设置信号处理函数来改变默认行为。

3、信号的使用

信号处理函数的注册

信号处理函数的注册不只一种方法,分为入门版和高级版

  1. 入门版:函数signal
  2. 高级版:函数sigaction

信号处理发送函数

信号发送函数也不止一个,同样分为入门版和高级版
1.入门版:kill
2.高级版:sigqueue

1.入门版

1.信号发送函数kill

kill 函数用于向指定进程发送信号

函数原型

int kill(pid_t pid, int sig);

  • pid 参数是目标进程的进程 ID(Process ID)。可以使用 getpid 函数获取当前进程的进程 ID,或者使用其他手段获取要发送信号的目标进程的进程 ID。
  • sig 参数是要发送的信号编号。可以使用预定义的宏(如 SIGTERMSIGKILL 等)来表示信号,也可以使用具体的信号编号。
示例:

通过命令行参数向指定进程发送信号

#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>int main(int argc, char **argv) {// 检查命令行参数数量if (argc < 3) {printf("用法:%s <信号编号> <进程ID>\n", argv[0]);exit(-1);}// 打印命令行参数信息printf("Command: %s, Signal: %s, Process ID: %s\n", argv[0], argv[1], argv[2]);// 将命令行参数转换为整数,得到信号编号和目标进程的进程 IDint sig = atoi(argv[1]);int pid = atoi(argv[2]);// 打印目标进程的进程 ID 和要发送的信号编号printf("目标进程ID:%d,信号编号:%d\n", pid, sig);// 使用 kill 函数向指定进程发送信号if (kill(pid, sig) == 0) {printf("信号发送成功 %d\n", pid);} else {perror("kill");exit(-1);}return 0;
}
2.信号处理函数的注册signal

用于设置信号处理函数,捕捉到相应的信号后调用处理函数

函数原型

typedef void (*sighandler_t)(int);(信号处理函数)typedef将这个类型的指针函数取了一个别名sighandler_t

sighandler_t signal(int signum, sighandler_t handler);

signal函数用于注册信号处理函数,接受两个参数:

  • signum:要处理的信号的编号。
  • handler:指向用户定义的信号处理函数的指针。设置成SIG_IGN表示忽略对于的信号

函数返回一个先前与该信号相关联的处理函数的指针,如果调用失败返回SIG_ERR,返回值的作用为了方便后续的操作,比如在程序结束时回复原来的信号处理函数。

示例:

使用注册信号处理函数捕捉(Ctrl+C) 键

#include <signal.h>
#include <stdio.h>// 定义信号处理函数的类型
typedef void (*sighandler_t)(int);// 函数原型:注册信号处理函数
// sighandler_t signal(int signum, sighandler_t handler);// 信号处理函数,处理接收到的信号
void handle(int signum)
{printf("接收到信号 %d\n", signum);
}int main()
{// 定义保存信号处理函数返回值的变量sighandler_t handler_t;// 使用 signal 函数注册信号处理函数handler_t = signal(SIGINT, handle);// 检查 signal 函数的返回值是否出错if (handler_t == SIG_ERR) {printf("signal 函数执行出错!\n");}// 进入无限循环,等待信号的到来while (1);return 0;
}

2.高级版

1. 信号处理发送函数sigqueue

函数用于向指定进程发送信号,与 kill 函数相比,sigqueue 提供了更多的灵活性。它可以携带一个整数值或指针作为辅助数据,用于传递更多信息给接收信号的进程

函数原型

int sigqueue(pid_t pid, int sig, const union sigval value);

  • pid:目标进程的进程 ID,指定信号要发送到的进程。
  • sig:要发送的信号的编号。
  • value:一个 union sigval 类型的结构,用于携带辅助数据

union sigval 结构定义如下

union sigval {int sival_int;      // 整数值void *sival_ptr;    // 指针值
};

 函数返回值为 0 表示成功,-1 表示失败,错误原因存储在 errno 中。

示例:
#include <signal.h>
#include <stdio.h>// int sigqueue(pid_t pid, int sig, const union sigval value);
// union sigval {
//     int   sival_int;
//     void *sival_ptr;
// };int main(int argc, char **argv) {// 定义 sigval 结构体用于携带辅助数据union sigval value;value.sival_int = 100;  // 替换成要传递的整数值// 从命令行参数获取目标进程的进程 ID 和要发送的信号编号int pid = atoi(argv[2]);int sig = atoi(argv[1]);// 使用 sigqueue 函数向指定的进程发送信号,并携带辅助数据if (sigqueue(pid, sig, value) == 0) {// 信号发送成功printf("信号成功发送至进程 %d,携带的整数值为 %d\n", pid, value.sival_int);} else {perror("sigqueue");}return 0;
}
2.信号处理函数的注册sigaction

sigaction 函数用于检查或修改指定信号的处理方式。这个函数允许程序员指定一个信号的处理函数,并提供了一些额外的控制选项。

函数原型

int sigaction(int signum, const struct sigaction *act,struct sigaction *oldact);

  • signum:要操作的信号的编号。
  • act:一个指向 struct sigaction 结构体的指针,用于指定新的信号处理方式。
  • oldact:一个指向 struct sigaction 结构体的指针,用于保存原来的信号处理方式

struct sigaction 结构体定义如下

struct sigaction {void (*sa_handler)(int);          // 函数指针,指定信号处理函数void (*sa_sigaction)(int, siginfo_t *, void *);  // 备用的信号处理函数sigset_t sa_mask;                 // 在信号处理函数执行期间阻塞的信号集int sa_flags;                     // 用于指定一些额外的标志void (*sa_restorer)(void);        // 废弃,无需关心
};

 sigaction 函数返回 0 表示成功,-1 表示出错,错误信息存储在 errno

sigaction函数的详细介绍有小红旗的是我们重点需要注意的 

 

 示例:
#include <signal.h>
#include <stdio.h>// 信号处理函数
void handler(int signum, siginfo_t *data, void *estimate)
{printf("Received signal: %d\n", signum);// 检查是否有传递的附加信息if (estimate != NULL){printf("Sender PID: %d, Data: %d, Value: %d\n", data->si_pid, data->si_int, data->si_value.sival_int);}
}int main()
{// 定义 struct sigaction 结构体struct sigaction act;act.sa_sigaction = handler;  // 设置信号处理函数为 handleract.sa_flags = SA_SIGINFO;   // 设置 sa_flags,表示使用 sa_sigaction 作为处理函数// 注册信号处理函数sigaction(10, &act, NULL);printf("Process PID: %d\n", getpid());// 让程序保持运行,等待信号while (1);return 0;
}

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

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

相关文章

数据结构排序——选择排序与堆排序(c语言实现)

数据结构排序——选择排序与堆排序&#xff08;c语言实现&#xff09; 今天继续排序的内容&#xff1a; 文章目录 1.选择排序1.1基本介绍1.2代码实现1.2.1基础款1.2.2进阶款 2.堆排序2.1基本介绍2.2代码实现 1.选择排序 1.1基本介绍 选择排序&#xff08;Selection Sort&#…

2023年最具影响力的十大网络安全事件,文件销毁,数据销毁,保密销毁,物料销毁,回收电脑 硬盘销毁

被业内人士定性为网络安全“灾年”的2023年已经翻篇&#xff0c;但过去一年发生的创记录的数据泄露、勒索软件、零日漏洞、间谍软件和供应链攻击事件已经为2024年全球网络安全威胁态势定下了主旋律和基调。 以下我们将回顾各行业2023年最具影响力和破坏力的十大网络安全事件&am…

十、基本对话框大集合(Qt5 GUI系列)

目录 一、设计需求 二、实现代码 三、代码解析 四、总结 一、设计需求 Qt提供了很多标准的对话框。例如标准文件对话框(QFileDialog)、标准颜色对话框(QColorDialog)、标准字体对话框 (QFontDialog)、标准输入对话框 (QInputDialog) 及消息对话框 (QMessageBox)。本文展示各…

leecode | 字符串中的额外字符

题意&#xff1a;给定一个s字符串&#xff0c;和一个字典 字符串数组d&#xff0c;现在将字符串通过字典中的字符串数组把s切分&#xff0c;求最后剩下无法再切的字符串的长度思路&#xff1a;动态规划 倒着切 s[n-1] 切不了 那么问题转换成 n-1 找到找到一个j 使得 s[j, n-1]…

基于卷积神经的车牌识别系统

项目介绍 本项目是一个基于卷积神经网络的车牌识别系统&#xff0c;旨在通过图像识别技术自动检测和识别车牌&#xff0c;并判断车牌类型。系统可以识别蓝牌、黄牌&#xff08;单双行&#xff09;、绿牌、大型新能源&#xff08;黄绿&#xff09;、领使馆车牌、警牌、武警牌&a…

C#.Net学习笔记——CLR核心机制

一、CLR基本介绍 &#xff08;1&#xff09;C(Common) L&#xff08;Language&#xff09; R&#xff08;Runtime&#xff09; IL的运行环境 &#xff08;2&#xff09;从下图可以看到&#xff0c;我们的计算机会先把我们写的语言&#xff0c;编写成IL语言&#xff0c;再给计…

21、Kubernetes核心技术 - 高可用集群搭建(kubeadm+keepalived+haproxy)

目录 一、简介 二、高可用集群架构说明 三、部署环境说明 四、高可用集群搭建 (1)、初始化所有节点 (2)、修改host文件 (3)、调整内核参数 (4)、所有节点安装Docker (4-1)、配置 docker 的阿里 yum 源 (4-2)、yum 安装 docker (4-3)、配置 docker 的镜像源 (4-4)…

攀登者2 - 华为OD统一考试

OD统一考试 分值: 200分 题解: Java / Python / C++ 题目描述 攀登者喜欢寻找各种地图,并且尝试攀登到最高的山峰。 地图表示为一维数组,数组的索引代表水平位置,数组的元素代表相对海拔高度。其中数组元素0代表地面。 例如:[0,1,2,4,3,1,0,0,1,2,3,1,2,1,0],代表如下…

win10录音功能大盘点,帮你轻松搞定录音

“有人知道win10系统怎么录音吗&#xff1f;在网上找到了一段英语听力&#xff0c;本来打算保存下来&#xff0c;但是发现不能下载&#xff0c;我也不会使用电脑录音&#xff0c;真的很头疼&#xff0c;有人能帮帮我吗。” 在Windows 10系统中&#xff0c;录音是一项常见但往往…

计算机网络学习笔记(四)

文章目录 1.介绍一下HTTPS的流程。2.介绍一下HTTP的失败码。3.说一说你知道的http状态码。4. 301和302有什么区别&#xff1f;5.302和304有什么区别&#xff1f;6. 请描述一次完整的HTTP请求的过程。7.什么是重定向&#xff1f;8. 重定向和请求转发有什么区别&#xff1f;9.介绍…

04 帧 Frame

文章目录 04 帧 Frame4.1 相机相关信息4.2 特征点提取4.2.1 特征点提取 ExtractORB()4.3 ORB-SLAM2对双目/RGBD特征点的预处理4.3.1 双目视差公式4.3.2 双目图像特征点匹配 ComputeStereoMatches()4.3.3 根据深度信息构造虚拟右目图像&#xff1a;ComputeStereoFromRGBD() 4.4 …

书生·浦语大模型全链路开源体系 学习笔记 第二课

基础作业&#xff1a; 使用 InternLM-Chat-7B 模型生成 300 字的小故事&#xff08;需截图&#xff09;。熟悉 hugging face 下载功能&#xff0c;使用 huggingface_hub python 包&#xff0c;下载 InternLM-20B 的 config.json 文件到本地&#xff08;需截图下载过程&#xf…

Dijkstra算法——邻接矩阵实现+路径记录

本文是在下面这篇文章的基础上做了一些补充&#xff0c;增加了路径记录的功能。具体Dijkstra的实现过程可以参考下面的这篇文章。 [jarvan&#xff1a;Dijkstra算法详解 通俗易懂](Dijkstra算法详解 通俗易懂 - jarvan的文章 - 知乎 https://zhuanlan.zhihu.com/p/338414118) …

谷歌提出「边界注意力」模型,实现超越像素级检测精度!微弱边界也逃不过

有些情况下&#xff0c;当面临分辨率较低的图像时&#xff0c;可能会在进行诸如目标检测和图像分割等任务时遇到一些挑战和阻碍。这是因为低分辨率图像可能丢失了细节信息&#xff0c;使得计算机视觉系统难以准确捕捉和理解图像中的关键特征。在这种背景下&#xff0c;传统的方…

教程:Centos6迁移旧虚拟机文件后的网络配置教程,完美解决虚拟机移动后的网络ip变化问题

博主在工作后,想整整之前大学的虚拟机集群,因此特意从之前的旧电脑把虚拟机文件给拷贝了过来,在导入到vm-workstation,顺便能启动虚拟机后,发现之前的静态ip已经跟现在的宿主机网络不一样。想着重新配置,但觉得太麻烦,故想到了修改网卡的mac地址+网卡重配置方法,完美解…

uniapp微信小程序投票系统实战 (SpringBoot2+vue3.2+element plus ) -后端架构搭建

锋哥原创的uniapp微信小程序投票系统实战&#xff1a; uniapp微信小程序投票系统实战课程 (SpringBoot2vue3.2element plus ) ( 火爆连载更新中... )_哔哩哔哩_bilibiliuniapp微信小程序投票系统实战课程 (SpringBoot2vue3.2element plus ) ( 火爆连载更新中... )共计21条视频…

普中STM32-PZ6806L开发板(有点悲伤的故事续-人灯还未了)

简介 继上篇 普中STM32-PZ6806L开发板(有点悲伤的故事) 说到 关于 普中STM32-PZ6806L开发板的LED流水灯也被烧坏掉了&#xff0c;再也无法玩流水灯, 内心充满了只会流水灯的不甘, 流水灯就是单片机的Hello World&#xff0c;怎么能没有呢&#xff1f; 事情发展 好巧不巧想起最近…

报错解决:RuntimeError: Error building extension ‘bias_act_plugin‘

系统&#xff1a; Ubuntu22.04&#xff0c; nvcc -V&#xff1a;11.8 &#xff0c; torch&#xff1a;2.0.0cu118 一&#xff1a;BUG内容 运行stylegan项目的train.py时遇到报错&#x1f447; Setting up PyTorch plugin "bias_act_plugin"... Failed! /home/m…

【linux】tcpdump 使用

tcpdump 是一个强大的网络分析工具&#xff0c;可以在 UNIX 和类 UNIX 系统上使用&#xff0c;用于捕获和分析网络流量。它允许用户截取和显示发送或接收过网络的 TCP/IP 和其他数据包。 一、安装 tcpdump 通常是默认安装在大多数 Linux 发行版中的。如果未安装&#xff0c;可…