当前位置: 首页 > news >正文

Linux进程信号--1、信号产生

目录

一、键盘产生

        1.1产生过程

        1.2过程图示(硬 + 软)

        1.3代码演示

二、Linux指令

三、系统调用

3.1本质

3.2举例

        3.2.1 kill

        3.2.2 raise

        3.2.3 abort

四、软件条件

        4.1 理解

        4.2 alarm演示

     4.2.1基于alarm实现理解OS运行

五、异常

        5.1 理解

        5.2 举例

          5.3 core dump 与 Term


一、键盘产生

        1.1产生过程

        键盘组合键(快捷键)按下被OS识别,在PCB中修改位图结构(前32个信号)(后面的信号为实时信号用不到)由0->1->0,根据比特位上的位置从对应的执行方法结构体函数指针数组上获得信号对应方法并执行。

注:

        1.硬件信号处理理解与执行过程详见中断之OS运行

        2.信号位图只能由OS改写,因为OS是进程的管理者

        3.软件信号处理理解

        1.2过程图示(硬 + 软)

        

        1.3代码演示

Ctrl+C (SIGINT) 已经验证过,这⾥不再重复
Ctrl+\(SIGQUIT)可以发送终⽌信号
Ctrl+Z(SIGTSTP)可以发送停⽌信号,将当前前台进程挂起到后台
.......
#include <iostream>
#include <unistd.h>
#include<signal.h>
#include<sys/types.h>void handler(int signum)
{std::cout << "我是: " << getpid() << ", 我获得了⼀个信号: " << signum << std::endl;exit(0);
}int main()
{std::cout << "我是进程: " << getpid() << std::endl;// //ctrl+\// signal(SIGQUIT/*3*/, handler);// //ctrl + z// signal(SIGTSTP/*20*/, handler);while(true){std::cout << "I am a process, I am waiting signal!" << std::endl;sleep(1);}
}

二、Linux指令

kill - SIGNUM PID

        -9信号无法被捕捉

三、系统调用

3.1本质

代码中利用函数调用系统调用系统调用,利用软中断向OS发送信号

3.2举例

        3.2.1 kill
kill 命令是调⽤ kill 函数实现的。 kill 函数可以给⼀个指定的进程发送指定的信号。
NAME
        kill - send signal to a process
SYNOPSIS
        #include <sys/types.h>
        #include <signal.h>
                int kill(pid_t pid, int sig);
RETURN VALUE
        On success (at least one signal was sent), zero is returned. On error, -1 is returned, and errno is set appropriately.
void Usage(char *argv[])
{std::cerr << "Usage: " << argv[0] << " -signumber pid" << std::endl;
}int main(int argc,char *argv[])
{//函数调用系统调用//1.自主实现killif(argc != 3){Usage(argv);return 1;}int number = std::stoi(argv[1]+1); // 去掉-pid_t pid = std::stoi(argv[2]);int n = kill(pid, number);return n;
}

        3.2.2 raise
raise 函数可以给当前进程发送指定的信号(⾃⼰给⾃⼰发信号)。
NAME
        raise - send a signal to the caller
SYNOPSIS
        #include <signal.h>
                int raise(int sig);
RETURN VALUE
        raise() returns 0 on success, and nonzero for failure.
//2.raisesignal(2, handler); // 先对2号信号进⾏捕捉// 每隔1S,⾃⼰给⾃⼰发送2号信号while(true){sleep(1);raise(2);}
     
        3.2.3 abort
abort 函数使当前进程接收到信号⽽异常终⽌。
NAME
        abort - cause abnormal process termination
SYNOPSIS
        #include <stdlib.h>
                void abort(void);
RETURN VALUE
        The abort() function never returns.
// 就像exit函数⼀样,abort函数总是会成功的,所以没有返回值
//3.abortsignal(SIGABRT, handler);while(true){sleep(1);abort();}

四、软件条件

        4.1 理解

软件条件不满足,导致发生软中断引发信号产生

eg:

        1.管道读端关闭,继续写OS就会杀掉该进程(13)号信号

        2.设置闹钟函数alarm()(14号信号)

        4.2 alarm演示

NAME
        alarm - set an alarm clock for delivery of a signal
SYNOPSIS
        #include <unistd.h>
                unsigned int alarm(unsigned int seconds);
RETURN VALUE
        alarm() returns the number of seconds remaining until any previously scheduled alarm was due to be delivered, or zero if there was no previ‐ ously scheduled alarm.

        4.2.1基于alarm实现理解OS运行
#include <iostream>
#include <unistd.h>
#include<signal.h>
#include<functional>
#include<vector>
#include<sys/types.h>//基于alarm实现理解OS运行using func_t = std::function<void()>;int gcount = 0;
//OS任务集
std::vector<func_t> gfuncs;// 把信号 更换 成为 硬件中断
void hanlder(int signo)
{for(auto &f : gfuncs){f();}std::cout << "gcount : " << gcount << std::endl;//持续发送14号信号alarm(1);
}int main()
{gfuncs.push_back([](){std::cout << "我是一个内核刷新操作" << std::endl; });gfuncs.push_back([](){std::cout << "我是一个检测进程时间片的操作,如果时间片到了,我会切换进程" << std::endl;});gfuncs.push_back([](){std::cout << "我是一个内存管理操作,定期清理操作系统内部的内存碎片" << std::endl;});alarm(1);signal(SIGALRM,hanlder);while(true){pause();gcount++;std::cout << "我醒来了..." << std::endl;}return 0;
}

五、异常

        5.1 理解

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

        5.2 举例

a.野指针 :段错误--11号信号
b.除0 :浮点数错误 --8号信号
#include <stdio.h>
#include <signal.h>
void handler(int sig)
{printf("catch a sig : %d\n", sig);
}
int main()
{//signal(SIGSEGV, handler);sleep(1);int *p = NULL;*p = 100;while(1);return 0;
}
#include <stdio.h> 1
#include <signal.h>
void handler(int sig)
{printf("catch a sig : %d\n", sig);
}
// v1
int main()
{//signal(SIGFPE, handler); // 8) SIGFPEsleep(1);int a = 10;a/=0;while(1);return 0;
}

      

          5.3 core dump 与 Term

        利用man 7 signal查看时我们会发现终止信号的处理方法分为Core 和 Term,其中Term是正常终止,但Core会产生dump文件用于事后调试(gdb)

        

http://www.xdnf.cn/news/1128007.html

相关文章:

  • 时间复杂度和空间复杂度是衡量一个算法好坏的标准
  • A*算法详解
  • 9、线程理论1
  • eVTOL分布式电推进(DEP)适航审定探究
  • redisson tryLock
  • Spring MVC2
  • 尚庭公寓-----day1----@MapperScan爆红问题
  • 三十二、【核心功能改造】数据驱动:重构仪表盘与关键指标可视化
  • 【转】Rust: PhantomData,#may_dangle和Drop Check 真真假假
  • 【字节跳动】数据挖掘面试题0019:带货直播间推荐:现在有一个带货的直播间,怎么把它精准地推送给有需要的用户
  • 【C++】神奇的AVL树
  • WebView JSBridge 无响应问题排查实录 全流程定位桥接调用失效
  • 无人机故障响应模块运行与技术难点
  • Ubuntu24 辅助系统-屏幕键盘的back按键在网页文本框删除不正常的问题解决方法
  • RTL编程中常用的几种语言对比
  • 【C#地图显示教程:实现鼠标绘制图形操作】
  • 厂区车辆导航系统:基于 GPS+AI 动态路径规划的技术实现与实践
  • 春秋云镜 initial
  • 2025开放原子开源生态大会 | openKylin的技术跃迁和全球协作
  • 2025开放原子开源生态大会 | 开源欧拉的AI原生实践与全球协作
  • GaussDB 数据库架构师修炼(三) 集群管理概览
  • 李宏毅《生成式人工智能导论》 | 第11讲-第14讲:大型语言模型的可解释性、能力评估、安全性
  • React源码5 三大核心模块之一:render,renderRoot
  • docker-compose 配置启动2个MongoDB
  • 【Docker基础】Dockerfile构建与运行流程完全指南:从原理到实践优化
  • PostgreSQL 超详细安装与使用教程:从入门到实战
  • Axios 和Express 区别对比
  • 使用LNMP一键安装包安装PHP、Nginx、Redis、Swoole、OPcache
  • Linux系统调优和工具
  • 理解 HTTP POST 请求中的 json 和 data 参数