Linux 信号signal处理机制

        Signal机制在Linux中是一个非常常用的进程间通信机制,很多人在使用的时候不会考虑该机制是具体如何实现的。signal机制可以被理解成进程的软中断,因此,在实时性方面还是相对比较高的。Linux中signal机制的模型可以采用下图进行描述。

         每个进程都会采用一个进程控制块对其进行描述,进程控制块中设计了一个signal的位图信息,其中的每位与具体的signal相对应,这与中断机制是保持一致的。当系统中一个进程A通过signal系统调用向进程B发送signal时,设置进程B的对应signal位图,类似于触发了signal对应中断。发送signal只是“中断”触发的一个过程,具体执行会在两个阶段发生:

1、  system call返回。进程B由于调用了system call后,从内核返回用户态时需要检查他拥有的signal位图信息表,此时是一个执行点。

2、  中断返回。进程被系统中断打断之后,系统将CPU交给进程时,需要检查即将执行进程所拥有的signal位图信息表,此时也是一个执行点。

        综上所述,signal的执行点可以理解成从内核态返回用户态时,在返回时,如果发现待执行进程存在被触发的signal,那么在离开内核态之后(也就是将CPU切换到用户模式),执行用户进程为该signal绑定的signal处理函数,从这一点上看,signal处理函数是在用户进程上下文中执行的。当执行完signal处理函数之后,再返回到用户进程被中断或者system call(软中断或者指令陷阱)打断的地方。

       Signal机制实现的比较灵活,用户进程由于中断或者system call陷入内核之后,将断点信息都保存到了堆栈中,在内核返回用户态时,如果存在被触发的signal,那么直接将待执行的signal处理函数push到堆栈中,在CPU切换到用户模式之后,直接pop堆栈就可以执行signal处理函数并且返回到用户进程了。Signal处理函数应用了进程上下文,并且应用实际的中断模拟了进程的软中断过程。

        最近写程序,各种bug各种错,有一回程序莫名退出,没报错,也没产生日志和core文件,貌似正常退出一样。

        但又不是在程序全部走完后退出,中途莫名退出,这就叫我想到了signal,应该是某些函数错误后发送kill信号给主进程,然后退出。

现在总结下signal各种类型:

Signal

Description

SIGABRT

由调用abort函数产生,进程非正常退出

SIGALRM

用alarm函数设置的timer超时或setitimer函数设置的interval timer超时

SIGBUS

某种特定的硬件异常,通常由内存访问引起

SIGCANCEL

由Solaris Thread Library内部使用,通常不会使用

SIGCHLD

进程Terminate或Stop的时候,SIGCHLD会发送给它的父进程。缺省情况下该Signal会被忽略

SIGCONT

当被stop的进程恢复运行的时候,自动发送

SIGEMT

和实现相关的硬件异常

SIGFPE

数学相关的异常,如被0除,浮点溢出,等等

SIGFREEZE

Solaris专用,Hiberate或者Suspended时候发送

SIGHUP

发送给具有Terminal的Controlling Process,当terminal被disconnect时候发送

SIGILL

非法指令异常

SIGINFO

BSD signal。由Status Key产生,通常是CTRL+T。发送给所有Foreground Group的进程

SIGINT

由Interrupt Key产生,通常是CTRL+C或者DELETE。发送给所有ForeGround Group的进程

SIGIO

异步IO事件

SIGIOT

实现相关的硬件异常,一般对应SIGABRT

SIGKILL

无法处理和忽略。中止某个进程

SIGLWP

由Solaris Thread Libray内部使用

SIGPIPE

在reader中止之后写Pipe的时候发送

SIGPOLL

当某个事件发送给Pollable Device的时候发送

SIGPROF

Setitimer指定的Profiling Interval Timer所产生

SIGPWR

和系统相关。和UPS相关。

SIGQUIT

输入Quit Key的时候(CTRL+\)发送给所有Foreground Group的进程

SIGSEGV

非法内存访问

SIGSTKFLT

Linux专用,数学协处理器的栈异常

SIGSTOP

中止进程。无法处理和忽略。

SIGSYS

非法系统调用

SIGTERM

请求中止进程,kill命令缺省发送

SIGTHAW

Solaris专用,从Suspend恢复时候发送

SIGTRAP

实现相关的硬件异常。一般是调试异常

SIGTSTP

Suspend Key,一般是Ctrl+Z。发送给所有Foreground Group的进程

SIGTTIN

当Background Group的进程尝试读取Terminal的时候发送

SIGTTOU

当Background Group的进程尝试写Terminal的时候发送

SIGURG

当out-of-band data接收的时候可能发送

SIGUSR1

用户自定义signal 1

SIGUSR2

用户自定义signal 2

SIGVTALRM

setitimer函数设置的Virtual Interval Timer超时的时候

SIGWAITING

Solaris Thread Library内部实现专用

SIGWINCH

当Terminal的窗口大小改变的时候,发送给Foreground Group的所有进程

SIGXCPU

当CPU时间限制超时的时候

SIGXFSZ

进程超过文件大小限制

SIGXRES

Solaris专用,进程超过资源限制的时候发送

signal对应的值:

POSIX.1中列出的信号:

SIGHUP 1 A 终端挂起或者控制进程终止 
SIGINT 2 A 键盘中断(如break键被按下) 
SIGQUIT 3 C 键盘的退出键被按下 
SIGILL 4 C 非法指令 
SIGABRT 6 C 由abort(3)发出的退出指令 
SIGFPE 8 C 浮点异常 
SIGKILL 9 AEF Kill信号 
SIGSEGV 11 C 无效的内存引用 
SIGPIPE 13 A 管道破裂: 写一个没有读端口的管道 
SIGALRM 14 A 由alarm(2)发出的信号 
SIGTERM 15 A 终止信号 
SIGUSR1 30,10,16 A 用户自定义信号1 
SIGUSR2 31,12,17 A 用户自定义信号2 
SIGCHLD 20,17,18 B 子进程结束信号 
SIGCONT 19,18,25 进程继续(曾被停止的进程) 
SIGSTOP 17,19,23 DEF 终止进程 
SIGTSTP 18,20,24 D 控制终端(tty)上按下停止键 
SIGTTIN 21,21,26 D 后台进程企图从控制终端读 
SIGTTOU 22,22,27 D 后台进程企图从控制终端写 

没在POSIX.1中列出,而在SUSv2列出

SIGBUS 10,7,10 C 总线错误(错误的内存访问) 
SIGPOLL A Sys V定义的Pollable事件,与SIGIO同义 
SIGPROF 27,27,29 A Profiling定时器到 
SIGSYS 12,-,12 C 无效的系统调用 (SVID) 
SIGTRAP 5 C 跟踪/断点捕获 
SIGURG 16,23,21 B Socket出现紧急条件(4.2 BSD) 
SIGVTALRM 26,26,28 A 实际时间报警时钟信号(4.2 BSD) 
SIGXCPU 24,24,30 C 超出设定的CPU时间限制(4.2 BSD) 
SIGXFSZ 25,25,31 C 超出设定的文件大小限制(4.2 BSD) 

(对于SIGSYS,SIGXCPU,SIGXFSZ,以及某些机器体系结构下的SIGBUS,Linux缺省的动作是A (terminate),SUSv2 是C (terminate and dump core))。 

下面是其它的一些信号 

信号 值 处理动作 发出信号的原因 
---------------------------------------------------------------------- 
SIGIOT 6 C IO捕获指令,与SIGABRT同义 
SIGEMT 7,-,7 
SIGSTKFLT -,16,- A 协处理器堆栈错误 
SIGIO 23,29,22 A 某I/O操作现在可以进行了(4.2 BSD) 
SIGCLD -,-,18 A 与SIGCHLD同义 
SIGPWR 29,30,19 A 电源故障(System V) 
SIGINFO 29,-,- A 与SIGPWR同义 
SIGLOST -,-,- A 文件锁丢失 
SIGWINCH 28,28,20 B 窗口大小改变(4.3 BSD, Sun) 
SIGUNUSED -,31,- A 未使用的信号(will be SIGSYS) 

(在这里,- 表示信号没有实现;有三个值给出的含义为,第一个值通常在Alpha和Sparc上有效,中间的值对应i386和ppc以及sh,最后一个值对应mips。信号29在Alpha上为SIGINFO / SIGPWR ,在Sparc上为SIGLOST。) 

处理动作一项中的字母含义如下 
A 缺省的动作是终止进程 
B 缺省的动作是忽略此信号 
C 缺省的动作是终止进程并进行内核映像转储(dump core) 
D 缺省的动作是停止进程 
E 信号不能被捕获 
F 信号不能被忽略 

 代码示例:

#include<stdio.h>  
#include<signal.h>  
#include<unistd.h>  
#include<stdlib.h>  
void when_alarm();  
void when_sigint();  
void when_sigchld(int);  
void when_sigusr1();  
void when_sigio();  
int main()  
{  int childpid;//子程序进程ID号  printf("程序已经开始运行,5秒钟后将接收到时钟信号。/n");  if ((childpid=fork())>0)//父进程  {  signal(SIGALRM,when_alarm);  //当接收到SIGALRM信号时,调用when_alarm函数  signal(SIGINT,when_sigint);  //当接收到SIGINT信号时,调用when_sigint函数  signal(SIGCHLD,when_sigchld);//当接收到SIGCHLD信号时,调用when_sigchld函数  signal(SIGUSR1,when_sigusr1);//当接收到SIGUSR1信号时,调用when_sigusr1函数  signal(SIGIO,when_sigio);//当接收到SIGIO信号时,调用when_sigio函数  alarm(5);     //5秒钟之后产生SIGALRM信号  raise(SIGIO); //向自己发送一个SIGIO信号  pause(); //将父进程暂停下来,等待SIGALRM信号到来  pause(); //将父进程暂停下来,等待SIGUSR1信号到来  pause(); //将父进程暂停下来,等待SIGCHLD信号到来  printf("------此时程序会停下来等待,请按下ctrl+c送出SIGINT信号-------/n");  pause(); //将父进程暂停下来,等待SIGINT信号到来          }  else if(childpid==0) //子进程  {  int timer;  for(timer=7;timer>=0;timer--) //时钟计时5秒产生SIGALRM信号,再过2秒子进程退出,产生SIGCHLD信号  {  if(timer>2)      printf("距离SIGALRM信号到来还有%d秒。/n",timer-2);  if(timer==4)  kill(getppid(),SIGUSR1); //向父进程发送一个SIGUSR1信号  if((timer<=2)&&(timer>0))  printf("子进程还剩%d秒退出,届时会产生SIGCHLD信号。/n",timer);  if(timer==0) //子进程退出,产生SIGCHLD信号  raise(SIGKILL); //子进程给自己发一个结束信号  sleep(1); //每个循环延时1秒钟  }          }  else  printf("fork()函数调用出现错误!/n");  return 0;  
}  
void when_alarm()  
{  printf("5秒钟时间已到,系统接收到了SIGALRM信号!/n");  
}  
void when_sigint()  
{  printf("已经接收到了SIGINT信号,程序将退出!/n");  exit(0);  
}  
void when_sigchld(int SIGCHLD_num)  
{  printf("收到SIGCHLD信号,表明我的子进程已经中止,SIGCHLD信号的数值是:%d。/n",SIGCHLD_num);  
}  
void when_sigusr1()  
{  printf("系统接收到了用户自定义信号SIGUSR1。/n");  
}  
void when_sigio()  
{  printf("系统接收到了SIGIO信号。/n");  
}
#include <unistd.h> 
#include <stdio.h> 
#include <stdlib.h> 
#include <signal.h> void handle_alarm(int i) 
{ printf("SIGALRM num is %d\n",i);printf("handle_alarm is excuted\n");exit(0); 
} void ctl_c(int j){printf("control+c is excuted\n");printf("SIGINT signal num  is %d \n",j);}
int main(int argc, char *argv[]) 
{ signal(SIGALRM, &handle_alarm); signal(SIGINT,ctl_c);alarm(3); while(1) {} 
} 

运行结果:


void handle_alarm(int i) ,得到的 i 表示SIGALRM中断号14;
void ctl_c(int j) ,得到的j表示的是SIGINT中断号2

         用户自定义的信号处理函数,只能有一个或者无参数,不然会报错,例如下例所示:handle_alarm函数定义两个形参,编译时报错。

#include <unistd.h> 
#include <stdio.h> 
#include <stdlib.h> 
#include <signal.h> void handle_alarm(int i,int p) 
{ printf("SIGALRM num is %d\n",i);printf("p is %d \n",p);printf("handle_alarm is excuted\n");exit(0); 
} void ctl_c(int j){printf("control+c is excuted\n");printf("SIGINT signal num  is %d \n",j);}
int main(int argc, char *argv[]) 
{ signal(SIGALRM, &handle_alarm); signal(SIGINT,ctl_c);alarm(3); while(1) {} 
} 

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

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

相关文章

Selenium自动化测试框架的搭建

说 起自动化测试&#xff0c;我想大家都会有个疑问&#xff0c;要不要做自动化测试&#xff1f; 自动化测试给我们带来的收益是否会超出在建设时所投入的成本&#xff0c;这个嘛别说是我&#xff0c;即便是高手也很难回答&#xff0c;自动化测试的初衷是美好的&#xff0c;而测…

ELK、ELFK日志分析系统

菜单一、ELK简介1.1 ELK组件说明1.1.1 ElasticSearch1.1.2 Kiabana1.1.3 Logstash 1.2 可以添加的其它组件1.2.1 Filebeat1.2.2 缓存/消息队列&#xff08;redis、kafka、RabbitMQ等&#xff09;1.2.3 Fluentd 1.3 为什么要用ELK1.4 完整日志系统的基本特征1.5 ELK 的工作原理 …

Linux初识网络基础

目录 网络发展 认识“协议 ” 网络协议 OSI七层模型&#xff1a; TCP/IP五层&#xff08;或四层&#xff09;模型 网络传输基本流程 网络传输流程图&#xff1a; 数据包封装和封用 网络中的地址 认识IP地址&#xff1a; 认识MAC地址&#xff1a; 网络发展 1.独立…

【云原生】Docker-compose中所有模块学习

compose模块 模板文件是使用 Compose 的核心&#xff0c;涉及到的指令关键字也比较多。但大家不用担心&#xff0c;这里面大部分指令跟 docker run 相关参数的含义都是类似的。 默认的模板文件名称为 docker-compose.yml&#xff0c;格式为 YAML 格式。 version: "3&quo…

STM32单片机蓝牙APP宠物自动喂食器定时语音提醒喂食系统设计

实践制作DIY- GC00162---蓝牙APP宠物自动喂食器 一、功能说明&#xff1a; 基于STM32单片机设计---蓝牙APP宠物自动喂食器 二、功能说明&#xff1a; STM32F103C系列最小系统板LCD1602显示器DS1302时钟模块5个按键语音播报模块ULN2003步进电机模块LED灯板HC-05蓝牙模块&#x…

检查网站是HTTP那种协议与获取域名的ipv6地址

前言 最近在做HTTPS的应用&#xff0c;可能需要使用ipv6的地址做SLB&#xff0c;但是怎么检查配置正确&#xff0c;总不能每次都看日志吧&#xff0c;实际上客户端也很容易查看&#xff0c;总结工作经验。 检查HTTP协议版本 笔者想到了使用浏览器方式&#xff0c;或者抓包&a…

春秋云镜 CVE-2020-26042

春秋云镜 CVE-2020-26042 Hoosk CMS v1.8.0 存在sql注入漏洞 靶标介绍 Hoosk CMS v1.8.0 install/index.php 存在sql注入漏洞。 启动场景 漏洞利用 SQL注入POC POST /install/index.php HTTP/1.1 Host: xxxx User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; r…

如何使用 ChatGPT 规划家居装修

你正在计划家庭装修项目&#xff0c;但不确定从哪里开始&#xff1f;ChatGPT 随时为你提供帮助。从集思广益的设计理念到估算成本&#xff0c;ChatGPT 可以简化你的家居装修规划流程。在本文中&#xff0c;我们将讨论如何使用 ChatGPT 有效地规划家居装修&#xff0c;以便你的项…

Ajax入门

文章目录 axios体验axios-查询参数常用请求方法数据提交 axios错误处理 axios体验 引入axios库 使用axios语法 axios({url: 目标资源地址 }).then((result)>{// 对服务器返回的数据做后续处理 })完整实例 <!DOCTYPE html> <html lang"en"><head&g…

Golang空结构体struct{}的作用是什么?

文章目录 占位符&#xff1a;通道标识&#xff1a;键集合&#xff1a;内存占用优化&#xff1a;总结&#xff1a; 在Go语言中&#xff0c;空结构体 struct{}是一种特殊的数据类型&#xff0c;它不占用任何内存空间。空结构体没有任何字段&#xff0c;也没有任何方法。尽管它看起…

Linux文本处理工具和正则表达式

Linux文本处理工具和正则表达式 一.查看、截取和修改文本的工具 1.查看文本的工具 cat 最常用的文件查看命令&#xff1b;当不指明文件或者文件名为一杠’-时&#xff0c;读取标准输入。 cat [OPTION]... [FILE]... -A&#xff1a;显示所有控制符(tab键:^I;行结束符:$) -…

Python web实战之Django的文件上传和处理详解

概要 关键词&#xff1a;Python Web开发、Django、文件上传、文件处理 今天分享一下Django的文件上传和处理。 1. 上传文件的基本原理 在开始深入讲解Django的文件上传和处理之前&#xff0c;先了解一下文件上传的基本原理。当用户选择要上传的文件后&#xff0c;该文件会被发…

拨开迷雾:利用全链路消息跟踪揭示系统奥秘

在分布式系统&#xff0c;一次外部请求往往需要内部多个模块&#xff0c;多个中间件&#xff0c;多台机器的相互调用才能完成。在这一系列的调用中&#xff0c;可能有些是串行的&#xff0c;而有些是并行的&#xff0c;排查定位非常困难。 全链路消息分析及全链路消息跟踪可以帮…

网络编程——深入理解TCP/IP协议——OSI模型和TCP/IP模型:构建网络通信的基石

TCP/IP协议— 一、简介 TCP/IP协议&#xff0c;即传输控制协议/互联网协议&#xff0c;是一组用于在计算机网络中实现通信的协议。它由两个主要的协议组成&#xff1a;TCP&#xff08;传输控制协议&#xff09;和IP&#xff08;互联网协议&#xff09;。TCP负责确保数据的可靠…

JWT的使用

文章目录 前言一、在yml文件中配置参数二、创建JwtUtil.java三、创建JwtProperties.java四、创建JwtClaimsConstant.java五、创建JwtTokenAdminInterceptor.java六、注册到WebMvcConfiguration1.4.3 ThreadLocal 前言 一、在yml文件中配置参数 sky:jwt:# 设置jwt签名加密时使…

八、Spring 整合 MyBatis

文章目录 一、Spring 整合 MyBatis 的关键点二、Spring 整合 MyBatis 的步骤2.1 创建 Maven 项目&#xff0c;并导入相关依赖2.2 配置 Mybatis 部分2.3 配置 Spring 部分2.3 配置测试类 一、Spring 整合 MyBatis 的关键点 1、 将 Mybatis 的 DataSource (数据来源)的创建和管理…

Electron + Vue3 + Vite + TS 构建桌面应用

之前是使用React、Electron、TS和webpack来构建桌面应用的。虽然功能齐全,但是打包等等开发的体验不太理想,总感觉太慢了。作为一个开发者,我们总是希望,执行构建命令后,可以快速打包或者启动本地应用,且通过更少的配置,来完成开发体验。 现在的vite已经得到广泛的应用…

林大数据结构【2019】

关键字&#xff1a; 哈夫曼树权值最小、哈夫曼编码、邻接矩阵时间复杂度、二叉树后序遍历、二叉排序树最差时间复杂度、非连通无向图顶点数&#xff08;完全图&#xff09;、带双亲的孩子链表、平衡二叉树调整、AOE网关键路径 一、判断 二、单选 三、填空 四、应用题 五、算…

cocos creator 的input.on 不生效

序&#xff1a; 1、执行input.on的时候发现不生效 2、一直按控制台也打印不出来console.log 3、先收藏这篇&#xff0c;因为到时候cocos要开发serveApi的时候&#xff0c;你得选一款趁手的后端开发并且&#xff0c;对习惯用ts写脚本的你来说&#xff0c;node是入门最快&#xf…

Pytorch Tutorial【Chapter 2. Autograd】

Pytorch Tutorial 文章目录 Pytorch TutorialChapter 2. Autograd1. Review Matrix Calculus1.1 Definition向量对向量求导1.2 Definition标量对向量求导1.3 Definition标量对矩阵求导 2.关于autograd的说明3. grad的计算3.1 Manual手动计算3.2 backward()自动计算 Reference C…