linux 信号与处理
一、linux信号是什么
- 基本概念
信号是事件发生时对进程的通知机制,也就是所谓的软件中断。信号和硬件的中断类似,是软件层对中断机制的模拟,在多数情况下是无法预测信号产生的时间,所以软件层提供了一种处理异步事件的方法。
二、 信号来源
信号的来源分为硬件来源和软件来源。
- 硬件来源:
- 硬件发生异常,即硬件检测到错误条件并通知内核,随即再由内核发送相应的信号给相关进程,如除数为0、无效的内存引用等。
- 用户按终端键,引起终端产生的信号(比如Ctrl + C键产生SIGINT)。
- 软件来源:
- 用户通过指令杀死,如kill指令。
- 发生软件事件, 如程序执行raise, alarm、setitimer、sigqueue等函数。
三、 信号处理
信号通常是发送给对应的进程,当信号到达后,该进程需要做出相应的处理措施,通常进程会视具体信号执行相应的操作,有三种操作方式。
- 忽略信号:
信号到达后、直接忽略,就好像是没有出该信号,信号对该进程不会产生任何影响。事实上,大多数信号都可以使用这种方式进行处理,但有两种信号却决不能被忽略,分别是SIGKILL 和 SIGSTOP。 - 捕获信号:
当信号到达进程后,执行signal()绑定好的信号处理函数。 - 执行系统默认操作:
进程不对该信号事件作出处理,而是交由系统进行处理,每一种信号都会有其对应的系统默认的处理方式。
四、常见信号
在linux系统中通过kill -l命令可以查看到相应的信号。信号编号是从 1 开始,不存在编号为 0 的信号,事实上 kill()函数对信号编号 0 有着特殊的应用。

注意:括号" ) "前面的数字对应该信号的编号,编号 1~31 所对应的是不可靠信号,编号 34~64 对应的是可靠信号,从图中可知,可靠信号并没有一个具体对应的名字,而是使用了 SIGRTMIN+N 或 SIGRTMAXN 的方式来表示。其中32和33空缺。
不可靠信号表
| 值 | 名称 | 解释 | 默认动作 |
|---|---|---|---|
| 1 | SIGHUP | 挂起 | |
| 2 | SIGINT | 中断 | |
| 3 | SIGQUIT | 退出 | |
| 4 | SIGILL | 非法指令 | |
| 5 | SIGTRAP | 断点或陷阱指令 | |
| 6 | SIGABRT | abort发出的信号 | |
| 7 | SIGBUS | 非法内存访问 | |
| 8 | SIGFPE | 浮点异常 | |
| 9 | SIGKILL | kill信号 | 不能被忽略、处理和阻塞 |
| 10 | SIGUSR1 | 用户信号1 | |
| 11 | SIGSEGV | 无效内存访问 | |
| 12 | SIGUSR2 | 用户信号2 | |
| 13 | SIGPIPE | 管道破损,没有读端的管道写数据 | |
| 14 | SIGALRM | alarm发出的信号 | |
| 15 | SIGTERM | 终止信号 | |
| 16 | SIGSTKFLT | 栈溢出 | |
| 17 | SIGCHLD | 子进程退出 | 默认忽略 |
| 18 | SIGCONT | 进程继续 | |
| 19 | SIGSTOP | 进程停止 | 不能被忽略、处理和阻塞 |
| 20 | SIGTSTP | 进程停止 | |
| 21 | SIGTTIN | 进程停止,后台进程从终端读数据时 | |
| 22 | SIGTTOU | 进程停止,后台进程想终端写数据时 | |
| 23 | SIGURG | I/O有紧急数据到达当前进程 | 默认忽略 |
| 24 | SIGXCPU | 进程的CPU时间片到期 | |
| 25 | SIGXFSZ | 文件大小的超出上限 | |
| 26 | SIGVTALRM | 虚拟时钟超时 | |
| 27 | SIGPROF | profile时钟超时 | |
| 28 | SIGWINCH | 窗口大小改变 | 默认忽略 |
| 29 | SIGIO | I/O相关 | |
| 30 | SIGPWR | 关机 | 默认忽略 |
| 31 | SIGSYS | 系统调用异常 |
五、信号处理
- signal()
"signal.h"信号处理库提供了signal函数,用来捕获突发事件。以下是 signal() 函数的语法ads。
typedef void (*sighandler_t)(int);
sighandler_t signal(int signum, sighandler_t handler);
- signum:可使用信号名(宏)或信号的数字编号,建议使用信号名。
- handler:参数 handler 既可以设置为用户自定义的函数,也可以设置为 SIG_IGN 或 SIG_DFL,SIG_IGN 表示此进程需要忽略该信号,SIG_DFL 则表示设置为系统默认操作。
- raise()
有时进程需要向自身发送信号,raise()函数可用于实现这一要求.
int raise(int sig);
- sig:需要发送的信号。
- sigaction()
除了signal()之外,sigaction()系统调用是设置信号处理方式的另一选择,虽然 signal()函数简单好用,而 sigaction()更为复杂,但作为回报,sigaction()也更具灵活性以及移植性。
int sigaction(int signum, const struct sigaction *act, struct sigaction *oldact);
- signum:需要设置的信号,除了 SIGKILL 信号和 SIGSTOP 信号之外的任何信号。
- act:参数 act 不为 NULL,则表示需要为信号设置新的处理方式;如果参数 act 为 NULL,则表示无需改变信号当前的处理方式
- oldact:参数oldact 不为 NULL,则会将信号之前的处理方式等信息通过参数 oldact 返回出来;如果无意获取此类信息,那么可将该参数设置为 NULL。
- 返回值:成功返回 0;失败将返回-1,并设置 errno。
struct 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);
};
- sa_handler:指定信号处理函数,与 signal()函数的 handler 参数相同。
- sa_sigaction:也用于指定信号处理函数,这是一个替代的信号处理函数。
- sa_mask:参数 sa_mask 定义了一组信号。
- sa_restorer:该成员已过时,不要再使用了。
- sa_flags:参数 sa_flags 指定了一组标志,这些标志用于控制信号的处理过程。
- kill()
kill()系统调用可将信号发送给指定的进程或进程组中的每一个进程。
int kill(pid_t pid, int sig);
- pid:参数 pid 为正数的情况下,用于指定接收此信号的进程 pid。
- sig:参数 sig 指定需要发送的信号,也可设置为 0,如果参数 sig 设置为 0 则表示不发送信号,但任执行错误检查,这通常可用于检查参数 pid 指定的进程是否存在。
- 返回值:成功返回 0;失败将返回-1,并设置 errno。
- alarm()
使用 alarm()函数可以设置一个定时器(闹钟),当定时器定时时间到时,内核会向进程发送 SIGALRM信号。
unsigned int alarm(unsigned int seconds);
- seconds:设置定时时间,以秒为单位;如果参数 seconds 等于 0,则表示取消之前设置的 alarm 闹钟。
- 返回值:如果在调用 alarm()时,之前已经为该进程设置了 alarm 闹钟还没有超时,则该闹钟的剩余值作为本次 alarm()函数调用的返回值,之前设置的闹钟则被新的替代;否则返回 0。
- pause()
pause()系统调用可以使得进程暂停运行、进入休眠状态,直到进程捕获到一个信号为止,只有执行了信号处理函数并从其返回时,pause()才返回,在这种情况下,pause()返回-1,并且将 errno 设置为EINTR。
int pause(void);
- 使用案例
demo1
#include <stdio.h>
#include <signal.h>
#include <stdlib.h>
#include <unistd.h>
void signal_handler(int signum)
{
printf("Interrupt signal (%d) received. \n", signum);
switch(signum){
case SIGINT:
printf("ctrl + c \n");
exit(signum);
break;
case SIGQUIT:
printf("ctrl + \\ \n");
exit(signum);
}
}
int main(int argc, char *argv[]) {
int i = 0;
//注册信号与信号处理程序
signal(SIGINT, signal_handler);
signal(SIGQUIT, signal_handler);
while(1)
{
printf("Going to sleep....\n");
if (i > 5){
raise( SIGINT);
}
sleep(1);
i++;
}
return 0;
}
参考文献
Linux信号(signal)机制:http://gityuan.com/2015/12/20/signal/
linux 信号及处理过程详解:https://blog.csdn.net/u010765526/article/details/80085895
linux kill信号详解:https://www.cnblogs.com/gcb-1991/p/6922694.html
《正点原子应用编程指南》
linux 信号与处理的更多相关文章
- Linux信号类型说明
说明 在Linux系统开发中经常要使用到信号来实现异步通知机制.而在Linux系统中信号有很多种,也不用全部记住,学习几种常见的信号,学会使用即可:当然也要知道用哪种方式能够发送这样的信号. 查看li ...
- Linux信号基础
Linux信号基础 作者:Vamei 出处:http://www.cnblogs.com/vamei 欢迎转载,也请保留这段声明.谢谢! Linux进程基础一文中已经提到,Linux以进程为单位来 ...
- Linux信号(signal) 机制分析
Linux信号(signal) 机制分析 [摘要]本文分析了Linux内核对于信号的实现机制和应用层的相关处理.首先介绍了软中断信号的本质及信号的两种不同分类方法尤其是不可靠信号的原理.接着分析了内核 ...
- 利用linux信号机制调试段错误(Segment fault)
在实际开发过程中,大家可能会遇到段错误的问题,虽然是个老问题,但是其带来的隐患是极大的,只要出现一次,程序立即崩溃中止.如果程序运行在PC中,segment fault的调试相对比较方便,因为可以通过 ...
- Linux信号实践(2) --信号分类
信号分类 不可靠信号 Linux信号机制基本上是从UNIX系统中继承过来的.早期UNIX系统中的信号机制比较简单和原始,后来在实践中暴露出一些问题,它的主要问题是: 1.进程每次处理信号后,就将对信号 ...
- 非常好的一篇对linux信号(signal)的解析 (转载)【转】
转自:https://blog.csdn.net/return_cc/article/details/78845346 Linux信号(signal) 机制分析 转载至:https://www.cnb ...
- Linux 信号:signal 与 sigaction
0.Linux下查看支持的信号列表: france@Ubuntux64:~$ kill -l ) SIGHUP ) SIGINT ) SIGQUIT ) SIGILL ) SIGTRAP ) SIGA ...
- Linux信号机制
Linux信号(signal) 机制分析 [摘要]本文分析了Linux内核对于信号的实现机制和应用层的相关处理.首先介绍了软中断信号的本质及信号的两种不同分类方法尤其是不可靠信号的原理.接着分析了内核 ...
- python学习笔记——多进程间通信——Linux信号基础
1 信号的基本描述 Signal信号(其全程为软中断信号)是Linux系统编程中非常重要的概念,信号是异步进程中通信的一种方式. 作用是通知进程发生了异步事件.进程之间可以调用系统来传递信号, 本身内 ...
- linux信号Linux下Signal信号太详细了,终于找到了
linux信号Linux下Signal信号太详细了,终于找到了 http://www.cppblog.com/sleepwom/archive/2010/12/27/137564.html
随机推荐
- RabbitMq死信队列(接盘侠)
队列创建之后,后期对其修改或者参数添加会报错.需要把队列重新删除,重新创建线上环境不能把队列删除,优雅安全的方式是重新建一个队列,把死信队列相关的队列进行绑定 在有过期时间的队列中设定最大接收能力5条 ...
- canvas——动画实例
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...
- 那些优秀的python代码
时间:2019-04-18 收藏:PangYuaner 标题:Python如何生成树形图案 地址:https://www.jb51.net/article/132049.htm 标题:用python- ...
- RapidSVN设置diff和edit工具
菜单栏 -> View -> Preferences -> Programs选择相应的配置页即可 需要配置的路径,默认都在 /usr/bin目录下的 editor可以用ged ...
- 用C++实现的Eratosthenes筛法程序
运行示例 只输出素数总数的运行示例 PS H:\Read\num\x64\Release> .\esieve.exe Eratosthenes sieve: a method to find o ...
- Centos7部署Open-falcon 0.2.0
官方和github上都有教程,但是对于我来说有的部署内容较为陌生,有点错误官方也未在教程中说明,故在此记录方便以后快速部署,本文部署的时间是2018/10/10. 虽然open-falcon是采用了前 ...
- tomcat漏洞总结
描述 Tomcat是Apache 软件基金会(Apache Software Foundation)的Jakarta 项目中的一个核心项目,由Apache.Sun 和其他一些公司及个人共同开发而成.由 ...
- 源码编译安装nginx及设置开机启动项
1.上传nginx文档:解压到/data目录下,并安装依赖包tar xf nginx-1.20.1.tar.gz -C /data/cd /data/nginx-1.20.1/ && ...
- Python常见问题 - python3 使用requests发送HTTPS请求报certificate verify failed 错误
当你使用 requests 发送HTTPS请求时 requests.get(url, parmas=parmas, headers=header, cookies=cookie) 出现了以下错误 HT ...
- Mysql 面试宝典
实时更新 你用过哪些数据库? mysql redis mysql 和 redis 的区别? 比较点 Mysql Redis 数据库类型 关系型 非关系型 作用 持久化层 存储需要持久化的数据,数据存在 ...