33 信号产生

目录

1.键盘信号
2.显示器回显过程
3.信号产生方式
4.总结

键盘信号

键盘数据是如何输入给内核的,crtl+c是怎么变成信号的?
键盘被按下,肯定是os先知道,os怎么知道键盘上有数据呢?

c让操作系统每隔一段时间去轮询每个硬件有没有数据消耗很大。所以cpu有很多针脚高低电平,每个针脚都对应了硬件的中断号,当硬件有数据时,通过中断单元给cpu发送硬件中断,充电和放电,根据中断号就知道哪个硬件有数据了,然后os将内容拷贝到对应文件的缓冲区,传给用户缓冲区。在内存操作系统部分,有一个中断向量表,里面保存了硬件方法的地址,调用这个方法就可以将键盘的数据读取到内存。拷贝完成后再次给cpu发送中断,继续之前的执行

在这里插入图片描述

os在拿到数据后会先判断,如果是控制类,如crtl+c,会转换为2号信号,不会拷贝到缓冲区

信号是模仿硬件中断的一种软件中断的方式

显示器回显的过程

显示器和键盘是两个文件,有自己对应的缓冲区,键盘输入后将内容拷贝到显示器的缓冲区就是回显。所以当后台运行时,输入命令后,虽然显示器显示是乱的,但仍然可以运行命令,就是因为内容是键盘缓冲区里,并没有在显示器缓冲区,只是回显到了显示器

在这里插入图片描述

信号产生方式

1.键盘组合键

crtl+c默认终止进程,除过这个快捷键还有crtl+\是3号信号
捕捉3号信号,运行验证:

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

using namespace std;
void myhandler(int signal)
{
    cout << "get a singal" << signal << endl;
}

int main()
{
    //signal(SIGINT, myhandler);
    signal(3, myhandler);

    while (true)
    {
        //printf("hello world\n");
        sleep(1);
    }
}

在这里插入图片描述
kill3号信号也是同样的结果
在这里插入图片描述

crtl+z是19号信号,捕捉19号信号发现不成功,crtl+z仍然会暂停进程,kill发送19号信号也暂停进程

不是所有的信号都可以被signal捕捉的,比如19

可以循环捕捉31个信号,然后kill从1发送到31,看看哪些信号不能捕获
结果9和19号新号不能捕捉
9和19号新号是杀死和暂停进程,为了防止恶意程序和重要工作运行正常不能被捕捉

SIGQUIT的默认处理动作是终止进程并且Core Dump

Core Dump

什么是Core Dump
当一个进程要异步终止时,可以选择把进程的用户空间内存数据全部保存到磁盘上,文件名通常是core,这叫core dump。进程异步终止通常是因为有bug,如非法访问导致段错误,事后可以用调试器检查core文件以查清错误原因,这叫做post-morterm debug(事后调试)。一个进程允许产生多大的core文件取决于进程的resource limit(这个信息保存在pcb中)。默认是不允许产生core文件的,因为core文件中可能包含用户密码等敏感信息,不安全。在开发调试阶段可以用ulimit命令改变这个限制,允许产生core文件,首先ulimit命令改变shell进程的resource limit允许core文件最大为1024k,$ulimit -c 1024

7章man手册
在这里插入图片描述

core dump 和term

ign是忽略,cont是继续。term和coredump都是终止,但有区别

这个标记之前在子进程status状态中说过,是第8位。生成子进程父进程等待获取一下coredump
在这里插入图片描述

#include <stdio.h>
#include <iostream>
#include <unistd.h>
#include <signal.h>
#include <sys/types.h>
#include <wait.h>

using namespace std;

void work()
{
    cout << "print log" << endl;
}
void myhandler(int signal)
{
    work();
    //cout << "get a singal" << signal << endl;
    int n = alarm(5);
    cout << "sencond: " << n << endl;
}

int main()
{
    //signal(SIGINT, myhandler);
    //signal(3, myhandler);
    // signal(SIGALRM, myhandler);
    // int n = alarm(50);
    // while (true)
    // {
    //     printf("%d\n", getpid());
    //     sleep(1);
    // }

    pid_t id = fork();
    if (id == 0)
    {
        while (true)
        {
            printf("我是子进程: %d\n", getpid());
            sleep(1);
        }
     
    }

    int status;
    pid_t ret = waitpid(id, &status, 0);
    printf("core dump: %d\n", status >> 7 & 1);
}

在这里插入图片描述在这里插入图片描述

云服务器的core功能被关闭的,ulimit -a可以查看所有,-c查看core的开关
在这里插入图片描述

ulimit -c 1024,设置大小为1024,开启功能,关闭设置为0

运行一个除0错误的代码,并生成一个core文件
在这里插入图片描述
在这里插入图片描述
打开系统的core dump功能,一旦出现异常,os会将进程在内存运行信息,转储到进程的当前目录,形成core.pid文件:核心转储(core dump)。这个可以让运行时错误,保存出现问题的在哪一行,先运行,再core-file,就是事后调试

运行gdb,直接输入core文件就可以定位打印错误信息

core-file [core文件]

在这里插入图片描述

core dump方便事后调试

为什么云服务器关掉这个功能,因为生成的core文件比较大,在一个比较大型的项目中,如果一出现这些错误就生成core文件,可能会导致生成特别多文件,占用很多资源,甚至导致运行被停止

2. kill

kill -sign pid

3. 系统调用

  1. kill命令是调用kill函数实现的。kill函数可以给一个指定的进程发送指定的信号

#include <signal.h>
int kill(pid_t pid, int signo);
int raise(int signo);
这两个函数都是成功返回0,错误返回-1。

在这里插入图片描述

自己实现kill命令

#include <stdio.h>
#include <iostream>
#include <unistd.h>
#include <signal.h>
#include <sys/types.h>

using namespace std;

void usage(string proc)
{
    cout << "usage:\n\t" << proc << "signum pid\n\n";
}

void myhandler(int signal)
{
    cout << "get a singal" << signal << endl;
}

//./kill 3 pid
int main(int args, char* argv[])
{
    if (args != 3)
    {
        usage(argv[0]);
        return 1;
    }

    int sign = stoi(argv[2]);
    pid_t pid = stoi(argv[1]);
    int n = kill(sign, pid);
    if (n < 0)
    {
        perror("kill");
        return 2;
    }
}

在这里插入图片描述

raise命令给当前进程发送指定信号

int raise(int signo);
这两个函数都是成功返回0,错误返回-1。

在这里插入图片描述

  1. abort可以给当前进程发送6号信号

#include <stdlib.h>
void abort(void);
就像exit函数一样,abort函数总是会成功的,所以没有返回值。

这个函数内部做了封装,调用后还会结束进程。如果是kill发送这种形式发6号信号,并不会结束进程

无论信号如何产生,一定是os发送的,因为os是进程的管理者

4. 异常

除0错误和野指针错误,这两个分别是8号和11号信号,发生这个错误会报告崩溃并退出。当对这两个信号捕捉,行为会改为一直循环
在这里插入图片描述

os如何知道异常

除0异常
cpu中的内容是进程的上下文数据,当cpu执行到除0错误的时候,会将cpu中的状态寄存器里的溢出标志位改为1,关于cpu的设计在cpu开发手册会有说明。cpu也是硬件,os是硬件的管理者,os发现这个这个标志就知道这个计算错误,然后给进程发送信号
在这里插入图片描述

野指针异常
cpu中继承了MMU(内存管理单元),这个可以进行虚拟地址和物理地址的页表转换,野指针就是地址转换失败的情况,cpu会将结果和失败的地址保存起来。os和上面一样发现这个错误就发送信号

为什么重复输出

当出现这个错误的时候没有结束进程,就会继续执行,当cpu再次加载进程的时候,发生的错误没有修复,又会继续发送信号,重复这个动作

硬件异常一方面没有权限去修复,是用户自己的数据。另一方面因为异常了,这个计算结果已经不值得信任。所以进程最好终止。信号和捕捉并不能解决这个异常,只是告诉用户明白出现的情况,可以统一处理

软件条件信号

异常不只可以由硬件产生,软件也可以。如管道中如果读取方关闭,就会发生异常,发送13号SIGPIPE信号并关闭写端。os检测条件不满足就会出现异常,可以这样产生闹钟

#include <unistd.h>
unsigned int alarm(unsigned int seconds);
调用alarm函数可以设定一个闹钟,也就是告诉内核在seconds秒之后给当前进程发SIGALRM信号, 该信号的默认处理动
作是终止当前进程。

这个函数到达设定延迟后会发送SIGALRM信号
返回值是0或者以前设定的闹钟时间还剩下的秒数。打个比方,某人要小睡一觉,设定闹钟为30分钟后响,20分钟后被吵醒了,还想多睡一会,重新设定闹钟为15分钟后响,这时以前设定的闹钟剩下的时间就是10分钟。如果参数为0,表示取消以前设定的闹钟,函数的返回值仍然是以前设定的闹钟时间还剩下的秒数

捕获闹钟信号验证:

#include <stdio.h>
#include <iostream>
#include <unistd.h>
#include <signal.h>
#include <sys/types.h>

using namespace std;
void myhandler(int signal)
{
    cout << "get a singal" << signal << endl;
}

int main()
{
    //signal(SIGINT, myhandler);
    //signal(3, myhandler);
    signal(SIGALRM, myhandler);
    int n = alarm(5);
    while (true)
    {
        printf("%d\n", getpid());
        sleep(1);
    }
    

}

在这里插入图片描述
闹钟不是异常,所以响应一次后就会结束,想让闹钟每隔5s响一次,可以重新设置

void myhandler(int signal)
{
    cout << "get a singal" << signal << endl;
    alarm(5);
}

在这里插入图片描述

闹钟可以设置一个定时任务

void work()
{
    cout << "print log" << endl;
}
void myhandler(int signal)
{
    work();
    cout << "get a singal" << signal << endl;
    alarm(5);
}

将闹钟时间设长,运行的时候kill发送信号,打印出返回值
在这里插入图片描述

os中一定存在大量的闹钟,将这些结构用组织管理起来,用系统当前时间和这些时间作对比,就能判断是否超时。超时了就发送对应的信号。这种用堆来管理最好,优先处理超时时间最近的,只要堆顶没超时,堆所有都没超时,就不需要遍历所有数据

总结

上面所说的所有信号产生,最终都要由os来执行,因为os是进程的管理者
信号可以是立即处理,也可以在合适的时候
信号如果不是被立即处理,那么信号是否需要暂时被记录下来,记录在哪里?怎么记录
一个进程在没有收到信号的时候,能否知道,自己应该对合法信号如何处理?
如何理解os向进程发送信号?能否描述一下完整的发送处理过程?

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Linux中Ctrl+C和Ctrl+Z的区别_实战讲解(超详细)

1、CtrlC和CtrlZ的区别&#xff1a; CtrlZ&#xff1a;暂停进程 即挂起进程 暂停当前进程并将其放到后台。可以在后续恢复执行。 暂停的进程仍然占用系统内存 CtrlC&#xff1a;终止进程 终止进程后&#xff0c;程序代码占用的内存会释放掉 2、实战讲解 跑人工智能代码的时候…

10.Java集合汇总

文章目录 1. Java集合概述1.1 Java集合框架概述1.2 Collection接口继承树1.3 Map接口继承树 2. Collection接口2.1 Collection接口方法 3 Iterator迭代器接口3.1 Iterator接口的方法3.2 foreach循环 4 List接口4.1 List接口方法4.1 ArrayList4.2 LinkedList4.3 Vector4.4 面试题…

如何通过大带宽优化美国站群服务器的全球访问速度?

如何通过大带宽优化美国站群服务器的全球访问速度? 在当今全球化的互联网时代&#xff0c;快速和稳定的网站访问对于企业至关重要。美国站群服务器因其地理位置和强大的网络基础设施而备受青睐&#xff0c;但要充分利用其优势&#xff0c;需要综合考虑多种因素。本文将探讨如…

233 基于matlab的多通道非负矩阵分解(MNMF)算法

基于matlab的多通道非负矩阵分解&#xff08;MNMF&#xff09;算法。其能够寻找到一个非负矩阵W和一个非负矩阵H&#xff0c;满足条件VW*H,从而将一个非负的矩阵分解为左右两个非负矩阵的乘积。使用EM准则对混合信号进行分解。程序已调通&#xff0c;可直接运行。 233 多通道非…

面试被刷,原因居然是不会Git

大家好&#xff0c;我是知微&#xff01; 假设你是一个刚入行的菜狗程序员&#xff0c;正在开发一个软件。 现在老板需要你加一些功能&#xff0c;此时的你有一些担忧&#xff0c;如果对代码进行大刀阔斧的改动&#xff0c;最终却失败了。之前能正常运行的代码也被改得乱七八糟…

商汤大模型一体机可节约80%推理成本,完成云端边全栈布局

商汤科技在上海举办技术交流日活动 会上商汤发布业内首个“云、端、边”全栈大模型产品矩阵&#xff0c;并推出全新升级的“日日新SenseNova 5.0”大模型体系。 影响至股价方面&#xff0c;商汤(00020.HK)今日开盘后大幅上涨。随后商汤在港交所公告称&#xff0c;商汤集团的…

《看漫画学C++》背后的故事1:艺术与科技的结合

引言&#xff1a; 在数字化浪潮中&#xff0c;艺术与科技的结合催生了无数创新。《看漫画学C》正是这一跨界合作的产物&#xff0c;它不仅是一本编程书籍&#xff0c;更是艺术与科技融合的典范。 一、相遇&#xff1a; 科技与艺术的火花作为一名专注于技术的软件程序员&…

【JAVA基础之IO】字节流、字符流以及乱码问题

&#x1f525;作者主页&#xff1a;小林同学的学习笔录 &#x1f525;mysql专栏&#xff1a;小林同学的专栏 目录 1. IO概述 1.1 什么是IO 1.2 IO的分类 1.3 字节和字符流的顶级父类 2. 字节流 2.1 一切皆为字节 2.2 字节输出流【OutputStream】 2.3 FileOutputStream类…

mfc140.dll丢失如何修复,分享多种有效的修复方法

在日常操作和使用电脑的过程中&#xff0c;我们可能会遇到一种较为常见的问题&#xff0c;即在尝试启动或运行某个应用程序时&#xff0c;系统突然弹出一个错误提示窗口&#xff0c;明确指出“mfc140.dll文件丢失”。这个mfc140.dll实际上是一个动态链接库文件&#xff08;DLL&…

Flask框架初探-如何在本机发布一个web服务并通过requests访问自己发布的服务-简易入门版

Flask框架初探 在接触到网络框架之前我其实一直对一个事情有疑惑&#xff0c;跨语言的API在需要传参的情况下究竟应该如何调用&#xff0c;之前做过的项目里&#xff0c;我用python做了一个代码使用一个算法得到一个结果之后我应该怎么给到做前端的同学或者同事&#xff0c;之前…

微信小程序使用echarts组件实现饼状统计图功能

微信小程序使用echarts组件实现饼状统计图功能 使用echarts实现在微信小程序中统计图的功能&#xff0c;具体的实现步骤思路可进我主页查看我的另一篇博文https://blog.csdn.net/weixin_45465881/article/details/138171153进行查看&#xff0c;本篇文章主要使用echarts组件实…

移动桌面均覆盖-免费使用,解锁VIP!

hello&#xff0c;我是小索奇 分享一下剪映&#xff0c;附带windows和移动端哈 软件内所有功能都已经解锁了哈&#xff01;不登录也是会员特权~ 相对于PR来说&#xff0c;用剪映省去了好多痛苦&#xff08;用过的都懂&#xff0c;都是包装&#xff09; 软件下载好之后双…

【计算机考研】计算机行业考研还有性价比吗?

刚上大学的时候觉得本科毕业就够了 到了大三找工作才发现自己什么都不会 只能踏上考研路 目前研一在读&#xff0c;身边有很多工作了几年又回来读研的同学&#xff0c;只能说现在计算机行业研究生还是比本科生有竞争力的 如果你的本科和我一样没有学什么技术&#xff0c;那…

实现Node.js安装与配置。

一 、Node.js简介 Node.js是一个基于Chrome V8引擎的JavaScript运行时环境&#xff0c;用于构建高性能、可扩展的网络应用程序。它发布于2009年5月&#xff0c;由Ryan Dahl开发&#xff0c;允许使用JavaScript进行服务器端编程&#xff0c;使开发者能够在前后端都使用同一种编程…

MessageBox的模版语法上如何注册事件

目标&#xff1a; 想要在MessageBox中的文本中写一些事件&#xff0c;如何处理 在vue中进行操作&#xff1a; coding // 弹窗提示 this.$confirm({customClass: "add-fail",title: this.$t(add_error),type: error,dangerouslyUseHTMLString: true, // 将消息使用…

【学习笔记二十六】EWM 盘点后台配置和前台演示

一、EWM盘点业务概述 SAP EWM(Extended Warehouse Management)模块中的盘点业务是一个关键流程,它允许企业对仓库中的库存进行实物清点,以确保系统中记录的数据与实际库存相符。盘点过程有助于企业识别库存差异,从而进行必要的库存调整,确保库存记录的准确性,这对于财务…

电商技术揭秘三十二:智能风控的案例研究与未来趋势

相关系列文章 电商技术揭秘相关系列文章合集&#xff08;1&#xff09; 电商技术揭秘相关系列文章合集&#xff08;2&#xff09; 电商技术揭秘二十八&#xff1a;安全与合规性保障 电商技术揭秘二十九&#xff1a;电商法律合规浅析 电商技术揭秘三十&#xff1a;知识产权保…

Excel 冻结前几行

Excel中有冻结首航和冻结首列的选项&#xff0c;但是如果想冻结前几行该怎么操作&#xff1f; 冻结首行或冻结首列 视图 -> 冻结窗格 -> 冻结首行或冻结首列 冻结前几行或前几列 视图 -> 冻结窗格 -> 冻结拆分窗格 具体冻结几行和几列取决于当前选中的单元格。…

leetcode 每日一题目 (树的直径 +DFS的深刻理解)

如下是题目的简单描述&#xff1a; 给你一棵二叉树的根节点 root &#xff0c;二叉树中节点的值 互不相同 。另给你一个整数 start 。在第 0 分钟&#xff0c;感染 将会从值为 start 的节点开始爆发。 每分钟&#xff0c;如果节点满足以下全部条件&#xff0c;就会被感染&…