[linux]进程信号(信号的概念,信号的产生方式,信号的相关接口、指令,函数,信号怎么保存(原理),信号怎么处理)

news/发布时间2024/5/15 7:01:02

目录

一、信号的概念

二、信号的产生方式

通过键盘发送信号

通过系统调用,指令

异常

软件条件

三、信号怎么保存(原理)

信号其他相关常见概念

在内核中表示 

sigset_t 

四、信号的相关接口、指令,函数 

signal

sigprocmask

sigpending

sigemptyset

sigfillset

sigaddset

sigdelset

sigismember

sigaction 

五、信号怎么处理

信号什么时候被处理?

信号的捕捉图


一、信号的概念

信号是进程之间事件异步通知的一种方式,属于软中断。

在linux中通过指令:kill -l 可以查看信号列表

二、信号的产生方式

通过键盘发送信号

如常用的ctrl + c就是向前台进程发送2号信号(SIGINT)

通过系统调用,指令

如:

kill -2 1234,意思是向pid为1234的进程发送2号信号

或者

#include <sys/types.h>
#include <signal.h>

int kill(pid_t pid, int sig);

作用:向指定pid的进程发送sig信号

返回值:如果成功(至少发送了一个信号),则返回0。如果出现错误,则返回-1,并适当地设置errno

异常

硬件异常被硬件以某种方式被硬件检测到并通知内核,然后内核向当前进程发送适当的信号。例如当前进程执行了除以0的指令,CPU的运算单元会产生异常,内核将这个异常解释为SIGFPE(8号)信号发送给进程。再比如当前进程访问了非法内存地址,,MMU会产生异常,内核将这个异常解释为SIGSEGV(11号)信号发送给进程。

软件条件

例如:

#include <unistd.h>
unsigned int alarm(unsigned int seconds);
调用alarm函数可以设定一个闹钟(闹钟也是一种软件条件),也就是告诉内核在seconds秒之后给当前进程发SIGALRM(14号)信号, 该信号的默认处理动作是终止当前进程。这个函数的返回值是0或者是以前设定的闹钟时间还余下的秒数。

三、信号怎么保存(原理)

信号其他相关常见概念

  • 实际执行信号的处理动作称为信号递达(Delivery)

  • 信号从产生到递达之间的状态,称为信号未决(Pending)。

  • 进程可以选择阻塞 (Block )某个信号。

  • 被阻塞的信号产生时将保持在未决状态,直到进程解除对此信号的阻塞,才执行递达的动作。

  • 注意,阻塞和忽略是不同的,只要信号被阻塞就不会递达,而忽略是在递达之后可选的一种处理动作。

在内核中表示 

  • 每个信号都有两个标志位分别表示阻塞(block)和未决(pending),还有一个函数指针表示处理动作。信号产生时,内核在进程控制块中设置该信号的未决标志,直到信号递达才清除该标志。在上图的例子中,SIGHUP信号未阻塞也未产生过,当它递达时执行默认处理动作。
  • SIGINT信号产生过,但正在被阻塞,所以暂时不能递达。虽然它的处理动作是忽略,但在没有解除阻塞之前不能忽略这个信号,因为进程仍有机会改变处理动作之后再解除阻塞。
  • SIGQUIT信号未产生过,一旦产生SIGQUIT信号将被阻塞,它的处理动作是用户自定义函数sighandler。如果在进程解除对某信号的阻塞之前这种信号产生过多次,将如何处理?POSIX.1允许系统递送该信号一次或多次。Linux是这样实现的:常规信号在递达之前产生多次只计一次,而实时信号在递达之前产生多次可以依次放在一个队列里。

sigset_t 

从上图来看,每个信号只有一个bit的未决标志,非0即1,不记录该信号产生了多少次,阻塞标志也是这样表示的。因此,未决和阻塞标志可以用相同的数据类型sigset_t来存储,sigset_t称为信号集,这个类型可以表示每个信号的“有效”或“无效”状态,在阻塞信号集中“有效”和“无效”的含义是该信号是否被阻塞,而在未决信号集中“有效”和“无效”的含义是该信号是否处于未决状态。

四、信号的相关接口、指令,函数 

signal

#include <signal.h>

typedef void (*sighandler_t)(int);

sighandler_t signal(int signum, sighandler_t handler);

功能:对信号进行自定义捕捉

参数:

signum:信号,如2号信号就填2或者SIGINT,注意:SIGKILL(9号)0和SIGSTOP(19号)不可忽略和自定义捕捉                                                           

handler:一个函数指针,函数内容为自定义的操作

返回值:成功返回自定义的函数指针,失败返回SIG_ERR。

 使用例子:

#include <signal.h>
#include <sys/types.h>
#include <unistd.h>#include <iostream>
using namespace std;
void handler(int signo)
{while (1){cout << "我是" << signo << "号信号,我被自定义捕捉了" << endl;sleep(1);}
}
int main()
{cout << getpid() << endl;signal(2, handler);while (1){cout << "我没有被自定义捕捉" << endl;sleep(1);}return 0;
}

sigprocmask

 #include <signal.h>

 int sigprocmask(int how, const sigset_t *set, sigset_t *oldset);
功能:读取或更改进程的信号屏蔽字(阻塞信号集,其存储结构为位图)

参数:

how:读取或更改方式

有三种选择:

假设当前的信号屏蔽字为mask。

  1. SIG_BLOCK:set包含了我们希望添加到当前信号屏蔽字的信号,相当于mask=mask|set
  2. SIG_UNBLOCK:set包含了我们希望从当前信号屏蔽字中解除阻塞的信号,相当于mask=mask&~set
  3. SIG_SETMASK:设置当前信号屏蔽字为set所指向的值,相当于mask=set

set:如果set不为非空指针,则按照set更改进程的屏蔽字

oldset:如果set和oldset都不为非空指针,则把先前信号的屏蔽字备份给oldset,再更改进程的屏蔽字,如果不许要备份先前信号的屏蔽字,则此参数设为nullptr

sigpending

  #include <signal.h>

  int sigpending(sigset_t *set);

功能:读取当前进程的未决信号集,通过set参数传出。调用成功则返回0,出错则返回-1。

sigemptyset

sigfillset

sigaddset

sigdelset

sigismember

#include <signal.h>

int sigemptyset(sigset_t *set);

int sigfillset(sigset_t *set);

int sigaddset(sigset_t *set, int signum);

int sigdelset(sigset_t *set, int signum);

int sigismember(const sigset_t *set, int signum);

功能:

sigemptyset()将set给出的信号集初始化为空,将所有信号从该集合中排除。

sigfillset()初始化set为full(比特位全为1),包括所有信号。

sigaddset()和sigdelset()分别从set中添加和删除信号符号。

sigismember()测试sigum是否是set的成员。

set:阻塞信号集

返回值:

sigemptyset()、sigfillset()、sigaddset()和sigdelset()成功时返回0,错误时返回-1。

sigismember()如果signum是set的成员返回1,如果signum不是set的成员返回0,如果出错返回-1。当出现错误时,这些函数设置errno来指示原因。

 上面函数的综合使用例子

#include <signal.h>
#include <sys/types.h>
#include <unistd.h>
#include <iostream>
using namespace std;void printsigset(sigset_t *s)
{for (int i = 31; i > 0; i--){if (sigismember(s, i)){cout << "1";}else{cout << "0";}}cout << endl;
}
int main()
{sigset_t s, p, o;sigemptyset(&s);for (int i = 1; i < 32; i++){sigaddset(&s, i);sigprocmask(SIG_BLOCK, &s, &p);cout << "前" << ": ";printsigset(&p);cout << "后" << ": ";printsigset(&s);sleep(2);}return 0;
}

解释代码

结果:1到31号信号都被阻塞(实际上9号和19号信号无法阻塞),以位图的形式打印出来

sigaction 

#include <signal.h>

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

解释:

sigaction函数可以读取和修改与指定信号相关联的处理动作。调用成功则返回0,  出错则返回- 1。signum是指定信号的编号。若act指针非空,则根据act修改该信号的处理动作。若oldact指针非空,则通过oldact传出该信号原来的处理动作。act和oldact指向sigaction结构体。

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函数自定义SIGINT信号的处理方式。要求:自定义处理函数名称为“sigcb”, 在sigcb当中完成打印信号值。

#include <signal.h>
#include <unistd.h>
#include <iostream>
using namespace std;void sigcb(int signo)
{while (1){cout << "我是" << signo << "号信号, 我被自定义处理了" << endl;sleep(2);}
}
int main()
{struct sigaction act;act.sa_handler = sigcb;sigaction(SIGINT, &act, NULL);while (1){cout << "我没有被自定义捕捉" << endl;sleep(2);}
}

 结果:

五、信号怎么处理

信号什么时候被处理?

信号发出后并不是立马递达的,而是进程从内核态返回用户态的时候,才对信号进行检查与处理。

信号的捕捉图

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

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

相关文章

Android基础开发-数据存储

SharedPreferences-xml 共享参数的用法 SharedPreferences是Android的一个轻量级存储工具&#xff0c;采用的存储结构是Key-Value的 键值对方式。 共享参数的存储介质是符合XML规范的配置文件。保存路径是:/data/data/应用包名/shared_prefs/文件名.xml 类似于java中的*.prop…

猜猜心里数字(个人学习笔记黑马学习)

1.定义一个变量&#xff0c;数字类型&#xff0c;内容随意 2.基于input语句输入猜想的数字&#xff0c;通过if和多次elif的组合&#xff0c;判断猜想数字是否和心里数字一致 num5if int(input("请输入第一次猜想的数字&#xff1a;"))5:print("猜对了&#xff0…

初谈软件工程(一)

我就读于兰州交通大学的软件工程专业。虽然在全国众多的985、211高校中&#xff0c;兰州交通大学可能并不显眼&#xff0c;似乎未能跻身这些所谓的“顶尖”行列就意味着不被认可。然而&#xff0c;在甘肃省的教育领域中&#xff0c;它无疑是一座璀璨的明珠&#xff0c;名列前茅…

el-table通过这样封装可以实现校验-表格校验的原理

我们一般在后台系统中&#xff0c;很常见的操作时表格里面嵌套表单&#xff0c;之前我的网上找到了一些封装的用法&#xff1a; <el-form :model"formData" :rules"ruleData" ref"formDom"><el-table :data"formData.tableData&q…

TCP面试问题集锦

1.TCP 三次握手过程&#xff1f; 目的是同步连接双方的序列号和确认号&#xff0c;并交换TCP窗口。 第一次握手&#xff0c;客户端发送(seqx)&#xff0c;客户端进入SYN_SEND状态&#xff1b; 第二次握手&#xff0c;服务端响应(Seqy, Ackx1)&#xff0c;服务器端就进入SYN_R…

springboot+vue网站开发-后端管理框架-vue-admin-template

为了方便国内用户下载&#xff0c;我把自己的百度网盘分享给大家一份地址&#xff0c;可以去下载。 如果你有上网盒子软件&#xff0c;那就自己去下载&#xff0c;很小。不到1MB. 链接&#xff1a;https://pan.baidu.com/s/15LJ2MoSWToFGFp28VaxBeQ?pwdbaby 提取码&#xff…

4核8G服务器并发数多少?性能如何?

腾讯云4核8G服务器支持多少人在线访问&#xff1f;支持25人同时访问。实际上程序效率不同支持人数在线人数不同&#xff0c;公网带宽也是影响4核8G服务器并发数的一大因素&#xff0c;假设公网带宽太小&#xff0c;流量直接卡在入口&#xff0c;4核8G配置的CPU内存也会造成计算…

普中51单片机学习(8*8LED点阵)

8*8LED点阵 实验代码 #include "reg52.h" #include "intrins.h"typedef unsigned int u16; typedef unsigned char u8; u8 lednum0x80;sbit SHCPP3^6; sbit SERP3^4; sbit STCPP3^5;void HC595SENDBYTE(u8 dat) {u8 a;SHCP1;STCP1;for(a0;a<8;a){SERd…

Docker硬件直通:如何在容器中高效利用GPU与硬盘资源

Docker硬件直通&#xff1a;如何在容器中高效利用GPU与硬盘资源 引言Docker基础容器与虚拟机的区别Docker的工作原理 访问服务器硬件资源概述为何需要在Docker容器中访问硬件资源可访问的硬件资源类型 在Docker中使用GPU配置Docker以使用宿主机的GPU资源安装NVIDIA Docker插件 …

CSS转换(2D)transform属性及animation动画

1、倾斜效果&#xff0c;旋转效果 <style type"text/css"> .transrorm_bar{ padding:150px; display: flex; align-items: center;} .transrorm_bar div{ width: 120px; height: 120px; background-color: #eee; margin: 10px; display: flex; align-items: c…

ES6 | (二)ES6 新特性(下) | 尚硅谷Web前端ES6教程

文章目录 &#x1f4da;迭代器&#x1f407;定义&#x1f407;工作原理&#x1f407;自定义遍历数据 &#x1f4da;生成器函数&#x1f407;声明和调用&#x1f407;生成器函数的参数传递&#x1f407;生成器函数案例 &#x1f4da;Promise&#x1f4da;Set&#x1f407;Set的定…

搭建私有Git服务器:GitLab部署详解

引言&#xff1a; 为了方便团队协作和代码管理&#xff0c;许多组织选择搭建自己的私有Git服务器。GitLab是一个集成了Git版本控制、项目管理、代码审查等功能的开源平台&#xff0c;是搭建私有Git服务器的理想选择。 目录 引言&#xff1a; 一、准备工作 在开始部署GitLab之…

数据分析(二):学生成绩预测分析报告

目录 摘要 一、引言 二、 数据源介绍 三、 数据清洗和预处理 3.1 缺失值处理 3.2 异常值处理 3.3 数据编码 四、 探索性数据分析 4.1 可视化相关统计量 4.2 目标数据的分布情况 4.3 Pearson 相关性分析 五、 特征工程 5.1 特征构造 5.1.1 总饮酒量 5.1.2 整体关…

type may not be empty [type-empty]

原因是使用了规范commit信息的工具&#xff0c;你的提交信息不符合规范&#xff0c;所以被拒绝了 commit规范工具 commitlinthusky 解决方式一&#xff1a; 修改提交信息&#xff0c; 使其符合规范 git commit -m "feat: 新功能"使用Git Gui的使用以下格式写提交…

Python爬虫-爬取B站番剧封面

本文是本人最近学习Python爬虫所做的小练习。如有侵权&#xff0c;请联系删除。 页面获取url 代码 import requests import os import re# 创建文件夹 path os.getcwd() /images if not os.path.exists(path):os.mkdir(path)# 当前页数 page 1 # 总页数 total_page 2# 自动…

electron安装最后一部卡住了?

控制台如下错误 不是的话基本可以划走了 这个很可能是镜像出现问题了&#xff0c;不一定是npm镜像 打开npm的配置文件添加下述 electron_mirrorhttps://cdn.npmmirror.com/binaries/electron/ electron_builder_binaries_mirrorhttps://npmmirror.com/mirrors/electron-build…

vue3+ts el-upload

vue文件 <template><div><el-uploadref"upload"class"upload-demo"dragmultipleaction"":disabled"disabled":auto-upload"true":limit"10":before-remove"beforeRemoveFn":on-preview…

pycallgraph,一个好用的 Python 代码可视化库!

目录 前言 什么是pycallgraph库&#xff1f; 安装pycallgraph库 使用pycallgraph库 pycallgraph库的功能特性 1. 支持多种输出格式 2. 支持定制化配置 3. 支持并发程序分析 示例代码 pycallgraph库的应用场景 1. 性能优化 2. 调试和错误排查 3. 代码维护和重构 4. 项目文…

Laravel03 路由到控制器与连接数据库

Laravel03 路由到控制器与连接数据库 1. 路由到控制器2. 连接数据库 1. 路由到控制器 如下图一些简单的逻辑处理可以放在web.php中&#xff0c;也就是路由的闭包函数里面。但是大的项目&#xff0c;我们肯定不能这么写。 为什么保证业务清晰好管理&#xff0c;都应该吧业务逻辑…

05-Linux部署MySQL

Linux部署MySQL 在今后的使用过程中&#xff0c;需要频繁使用Linux系统&#xff0c;所以在Linux上安装软是必不可少的操作 。 前置要求 需要学习前四章知识&#xff0c;初识Linux、Linux基础命令、Linux权限管理、Linux高阶技巧这4个章节。需要开启多态虚拟机&#xff0c;电…
推荐文章