【Linux 信号】信号的产生方式、信号的捕捉的全过程

news2024/11/17 11:38:27

信号的处理方式是远远比信号的产生

  • 当闹钟响了就知道时间到了,说明对应信号处理方法比信号产生更早

  • 操作系统的信号处理方法在编写操作系统的时候就已经编写好了

  1. signal函数

1.1所有的信号

1.2 signal函数的概念和简单使用

  • 捕捉信号就是自定义对应的信号的处理方法

  • 9号信号杀死进程;不可以被捕捉,因为如果被捕捉,那么对应进程就是无敌的不能被杀死

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

void headler(int signo)
{
    printf("signal NO.%d change\n",signo);
}
int main()
{
    signal(2,headler);//函数名不加()就是一个函数指针
    while(1)
    {
        printf("hello world  pid: %d\n",getpid());
        sleep(1);
    }
    return 0;
}

执行结果:ctrl+c发送二号信号,二号信号默认是终止进程

2.信号的产生方式

2.1.键盘产生

Ctrl+c 2号信号
Ctrl+\ 3号信号
Ctrl+z 20号信号

给对应进程发对应信号,命令格式:kill -信号编号 进程的pid

2.2程序奔溃,OS给进程发信号

代码中有一个除零错误

#include<stdio.h>
#include<unistd.h>
#include<signal.h>
void headler(int signo)
{
    printf("signal NO.%d change\n",signo);
}
int main()
{
    int i=1;
    while(i<=31){//捕获“”所有”信号
        signal(i,headler);
        i++;
    }
    int tem=10;//除零错误
    tem/=0;
    return 0;
}

执行错误:会发送一个8号信号

2.3.系统调用

kill:给任意一个进程发任意信号

raise:给当前进程发信号

2.4软件条件

概念:通过某种软件(OS),来触发信号的发送定时器或者某种操作达到条件不就绪等这样等场景,来触发信号发送;

  1. 定时器或者某种操作达到条件不就绪:比如管道的读端不写且关闭读端,那么就会向写端发送SIGPIPE信号

2.alarm定时器

2.4.1.可以使用alarm证明CPU的计算速度远大于打印的速度

1s中count计算打印了多少次;

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

int main()
{
    int count=0;
    alarm(1);
    while(1){
        count++;
        printf("count: %d\n",count);
    }
    return 0;
}

1s中count计算会有多少次

#include<stdio.h>
#include<unistd.h>
#include<signal.h>
int count=0;
void handler(int signo)
{
    printf("count: %d\n",count);
}

int main()
{
    alarm(1);
    signal(14,handler);
    while(1)
    {
        count++;

    }
    return 0;
}

执行结果:可以证明CUP计算速度远大于打印速度

3.OS如何识别信号

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

  1. 信号从产生到递达之间的状态,称为信号未决(Pending);(接受到信号了,但是还没有处理)

  1. 进程可以选择阻塞 (Block )某个信号;(保持这个信号为未决)

识别信号

  1. 先看block位图(也叫信号屏蔽字)是否被阻塞;

  1. 如果没有阻塞再看pending位图是否接收到信号;

  1. 如果接收到信号再看handler函数指针数组按SIG_DFL(默认)、SIG_IGN(忽略)、具体的函数指针就是自定义执行

4.信号集操作函数

4.1.sigset_t的接口

sigset_t是一个位图结构

#include<signal.h>
i nt sigemptyset(sigset_t *set);//初始化对象,全为设为为0
int sigfillset(sigset_t *set);//把所有信号置为1
int sigaddset (sigset_t *set, int signo);//把几号信号为1
int sigdelset(sigset_t *set, int signo);//把几号信号为0
int sigismember(const sigset_t *set, int signo); //判断是否有几号信号,返回真1假0

4.2.sigprocmask

调用函数sigprocmask可以读取或更改进程的信号屏蔽字(阻塞信号集)。

#include<signall.h>
int sigprocmask(int how, const sigset_t *set, sigset_t *oset); 返回值:若成功则为0,若出错则为-1

4.3.sigpending

#include<signal.h>
sigpending(sigset_t* set);
读取当前进程的未决信号集

4.4.简单使用

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

void show(sigset_t* set)
{
    int i=1;
    while(i<32)
    {
        if(sigismember(set,i))//信号为1则为真
            printf("1");
        else
            printf("0");
        i++;
    }
    printf("\n");
}
int main()
{
    sigset_t iset,pending;
    sigemptyset(&iset);//初始化

    sigaddset(&iset,2);//添加2号信号
    sigprocmask(SIG_SETMASK,&iset,NULL);//把信号屏蔽字改为iset
    while(1){
        sigemptyset(&pending);//初始化
        sigpending(&pending);//获取pending位图
        show(&pending);
        sleep(1);
    }
    return 0;
}

执行结果:屏蔽了2号信号,2号信号是未决的

5.信号的捕捉的全过程和信号的处理时机

信号的处理时机:从内核态返回到用户态,做信号的检测并处理;

6.volatile

volatile:告诉编译器,不要优化被volatile修饰的变量

#include<stdio.h>
#include<unistd.h>
#include<signal.h>
#include<iostream>
using namespace std;
int main()
{
    const int t=10;
    int* p=const_cast<int*>(&t);
    *p=20;
    printf("t: %d\n",t);
    printf("*p: %d\n",*p);
    return 0;
}

执行结果:t被const修饰,编译器去t的值不会取内存中取

volatile const int t=10;//既可以解决

7.SIGCHLD信号

SIGCHLD:当子进程退出会给父进程发17号信号SIGCHLD

#include<unistd.h>
#include<signal.h>
#include<iostream>
using namespace std;
void handler(int signo)
{
    cout<<signo<<endl;
    cout<<getpid()<<endl;
}
int main()
{
    signal(SIGCHLD,handler);
    if(fork()==0)
    {
        int cnt=5;
        while(cnt)
        {
            cout<<"I am child process, "<<getpid()<<endl;
            cnt--;
            sleep(1);
        }
        return 0;
    }
    while(1);
}

可以使用下面代码替换上面的signal(SIGCHLD,handler);就可以做到在不需要子进程的退出信息时自动释放

signal(SIGCHLD,SIG_IGN);

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

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

相关文章

【ArcGIS Pro二次开发】(1):开发环境配置

要想进行ArcGIS Pro的二次开发&#xff0c;需要安装【Visual Studio】、【ArcGIS Pro】软件和【ArcGIS Pro SDK】组件。在版本选择上&#xff0c;我选了最新的ArcGIS Pro3.0&#xff0c;对应的VS版本为Visual Studio 2022。 一、Visual Studio2022的安装 1、前往官网https://v…

【STM32】【HAL库】遥控关灯0 概述

相关连接 【STM32】【HAL库】遥控关灯0 概述 【STM32】【HAL库】遥控关灯1主机 【STM32】【HAL库】遥控关灯2 分机 【STM32】【HAL库】遥控关灯3 遥控器 需求 家里有几个房间,开关距离床都挺远的 睡觉想要关灯的时候需要下床 因此设计了本次项目 需要满足以下要求: 可以控…

【C1】数据类型,常量变量,输入输出,运算符,if/switch/循环,/数组,指针,/结构体,文件操作,/编译预处理,gdb,makefile,线程

文章目录1.数据类型&#xff1a;单双引号&#xff0c;char&#xff08;1B&#xff09;&#xff0c;int/float&#xff08;32位系统&#xff0c;大小一样4B&#xff0c;但存储方式不同&#xff09;&#xff0c;double&#xff08;8B&#xff09;&#xff0c;long double&#xf…

补充一些前端面试题

javascript有哪些库指路>js中的库uniapp和vue有什么区别什么是uniappuni-app&#xff08;uni&#xff0c;读you ni&#xff0c;是统一的意思&#xff09;是一个使用Vue.js开发所有前端应用的框架&#xff0c;开发者编写一套代码&#xff0c;可发布到iOS、Android、Web&#…

天工开物 #5 我的 Linux 开发机

首先说一下结论&#xff1a;最终我选择了基于 Arch Linux[1] 的 Garuda Linux[2] 发行版作为基础来搭建自己的 Linux 开发机。Neofetch 时刻发行版的选择在上周末的这次折腾里&#xff0c;我一共尝试了 Garuda Linux 发行版&#xff0c;原教旨的 Arch Linux 发行版&#xff0c;…

R语言读取Excel表格数据并绘制多系列柱状图、条形图

本文介绍基于R语言中的readxl包与ggplot2包&#xff0c;读取Excel表格文件数据&#xff0c;并绘制具有多个系列的柱状图、条形图的方法。 首先&#xff0c;我们配置一下所需用到的R语言readxl包与ggplot2包&#xff1b;其中&#xff0c;readxl包是用来读取Excel表格文件数据的&…

android---WebView实例

现在很多 App 里都内置了 Web 网页&#xff0c;比如电商平台淘宝、京东等。那么这种该如何实现呢&#xff1f;其实这是 Android 里一个叫 WebView 的组件实现的。下面将介绍 WebView 的实例。下面的实例是以组件化为基础搭建的。 新建项目 WebView&#xff0c;然后对整个项目做…

网络安全攻防中,Rock-ON自动化的多功能网络侦查工具,Burpsuite被动扫描流量转发

网络安全攻防中&#xff0c;Rock-ON自动化的多功能网络侦查工具&#xff0c;Burpsuite被动扫描流量转发。 #################### 免责声明&#xff1a;工具本身并无好坏&#xff0c;希望大家以遵守《网络安全法》相关法律为前提来使用该工具&#xff0c;支持研究学习&#xff…

linux003之远程操作

Xshell简介&#xff1a; Xshell 是一个强大的安全终端模拟软件&#xff0c;它支持SSH1, SSH2, 以及Microsoft Windows 平台的TELNET 协议。Xshell 通过互联网到远程主机&#xff0c;可以操控到linux服务器。  Xshell可以在Windows界面下用来访问远端不同系统下的服务器&#…

一些常见错误

500状态码: 代表服务器业务代码出错, 也就是执行controller里面的某个方法的过程中报错, 此时在IDEA的控制台中会显示具体的错误信息, 所以需要去看IDEA控制台的报错404状态码: 找不到资源找不到静态资源 检查请求地址是否拼写错误 检查静态资源的位置是否正确 如果以上都没有问…

Docker中安装Oracle-12c

前言 MySQL和Oracle是开发中常用到的两个关系型数据库管理系统&#xff0c;接上一期内容&#xff0c;这一期在Docker中完成oracle-12c的安装和配置。 安装oracle-12c 1、拉取oracle-12c镜像 启动Docker Desktop后在cmd窗口中执行docker search oracle命令&#xff0c;搜索O…

LeetCode-1138. 字母板上的路径【哈希表,字符串】

LeetCode-1138. 字母板上的路径【哈希表&#xff0c;字符串】题目描述&#xff1a;解题思路一&#xff1a;首先考虑坐标位置&#xff0c;字符是有序的从0开始&#xff0c;当前字符c的行为(c-a)/5,列为(c-a)%5。其次是考虑特殊情况z。若当前从‘z’开始则只能往上走;若是其他字符…

Spring MVC 之返回数据(静态页面、非静态页面、JSON对象、请求转发与请求重定向)

文章目录1. 默认情况下返回静态页面2. 返回一个非静态页面的数据2.1 ResponseBody 返回页面内容2.2 RestController ResponseBody Controller3. 实现登录功能&#xff0c;返回 JSON 对象3.1 前端使⽤ ajax&#xff0c;后端返回 json 给前端3.2 前端发送 JSON 的标准格式4. 请…

ChatGPT 怎么用最新详细教程一看就会

ChatGPT 以其强大的信息整合和对话能力惊艳了全球&#xff0c;在自然语言处理上面表现出了惊人的能力。这么强大的工具我们都想体验一下&#xff0c;那么 ChatGPT 怎么用呢&#xff1f;本文将给你逐步详细介绍。 使用 ChatGPT 主要有4步&#xff1a; 注册 ChatGPT 账号通过短…

Maven_第五章 核心概念

目录第五章 其他核心概念1、生命周期①作用②三个生命周期③特点2、插件和目标①插件②目标3、仓库第五章 其他核心概念 1、生命周期 ①作用 为了让构建过程自动化完成&#xff0c;Maven 设定了三个生命周期&#xff0c;生命周期中的每一个环节对应构建过程中的一个操作。 …

智慧办公管理系统

随着大数据、物联网和新一代通讯技术的发展&#xff0c;智慧地球、智慧城市、智慧办公正在逐步变成现实。 智慧办公管理系统主要分为会议室管理、考勤管理以及系统设置三部分功能。 架构图&#xff1a; 功能介绍 一、会议室管理 &#xff08;1&#xff09;、会议室信息 会议室…

如何将 Windows 11/10 许可证转移到另一台 PC

如果您最近购买了新的台式机或笔记本电脑&#xff0c;您可能希望在上面安装 Windows 11。对于某些用户来说&#xff0c;为新计算机购买新的 Windows 11 许可证可能会有点贵。 但是&#xff0c;如果您在旧计算机上安装了 Windows 11 并购买了一台新计算机来替换它&#xff0c;您…

JavaSE-线程池(1)- 线程池概念

JavaSE-线程池&#xff08;1&#xff09;- 线程池概念 前提 使用多线程可以并发处理任务&#xff0c;提高程序执行效率。但同时创建和销毁线程会消耗操作系统资源&#xff0c;虽然java 使用线程的方式有多种&#xff0c;但是在实际使用过程中并不建议使用 new Thread 的方式手…

【c++】数据类型

文章目录整型实型科学计数法sizeof关键字字符型字符串类型转义字符bool布尔类型c规定在创建一个变量或者常量时&#xff0c;必须要指定出相应的数据类型&#xff0c;否则无法给变量分配内存。 整型 作用&#xff1a;整型变量表示的是整数类型的数据。 实型 float f3.14; //默…

JavaCollection集合

5 Collection集合 5.1 Collection集合概述 是单列集合的顶层接口&#xff0c;它表示一组对象&#xff0c;这些对象也称Collection元素JDK不提供此接口的直接实现&#xff0c;它提供更具体的子接口&#xff08;Set 和 List&#xff09;实现 package ceshi;import java.util.A…