首页 > 代码库 > 信号概述
信号概述
中断概念
中断是系统对于异步事件的响应
中断信号
中断源
现场信息
中断处理程序
中断向量表
异步事件的响应:进程执行代码的过程中可以随时被打断,然后去执行异常处理程序
生活中的中断和计算机系统中的中断
1)无中断生活场景
张三看书,厨房烧水
2)有中断的生活场景
张三看书,设置闹钟,厨房烧水。
闹钟发出中断信号,张三把书合好(第20页),去厨房把开水事情处理好,张三重新打开20页进行阅读。
3)计算机系统的中断场景
中断源发出中断信号,CPU判断中断是否屏蔽、保护现场 ,CPU执行中断处理程序, CPU恢复现场,继续原来的任务。
中断的其他概念
中断向量表保存了中断处理程序的入口地址。
中断个数固定,操作系统启动时初始化中断向量表。
中断有优先级(有人敲门,有人打电话,有优先级)
中断可以屏蔽(张三可以屏蔽电话)。
中断分类
硬件中断(外部中断)
外部中断是指由外部设备通过硬件请求的方式产生的中断,也称为硬件中断
软件中断(内部中断)
内部中断是由CPU运行程序错误或执行内部程序调用引起的一种中断,也称为软件中断。
如:x86平台INT指令 ARM软中断指令SWI
信号概念
信号是UNIX系统响应某些状况而产生的事件,进程在接收到信号时会采取相应的行动。
信号是因为某些错误条件而产生的,比如内存段冲突、浮点处理器错误或者非法指令等.
信号是在软件层次上对中断的一种模拟,所以通常把它称为是软中断.
信号 VS. 中断
信号与中断的相似点:
(1)采用了相同的异步通信方式;
(2)当检测出有信号或中断请求时,都暂停正在执行的程序而转去执行相应的处理程序;
(3)都在处理完毕后返回到原来的断点;
(4)对信号或中断都可进行屏蔽。
信号与中断的区别:
(1)中断有优先级,而信号没有优先级,所有的信号都是平等的;
(2)信号处理程序是在用户态下运行的,而中断处理程序是在核心态下运行;
(3)中断响应是及时的,而信号响应通常都有较大的时间延迟。
信号名称及常用信号
信号名称 描述
SIGABRT 进程停止运行 6
SIGALRM 警告钟
SIGFPE 算述运算例外
SIGHUP 系统挂断
SIGILL 非法指令
SIGINT 终端中断 2
SIGKILL 停止进程(此信号不能被忽略或捕获)
SIGPIPE 向没有读者的管道写入数据
SIGSEGV 无效内存段访问
SIGQUIT 终端退出 3
SIGTERM 终止
SIGUSR1 用户定义信号1
SIGUSR2 用户定义信号2
SIGCHLD 子进程已经停止或退出
SIGCONT 如果被停止则继续执行
SIGSTOP 停止执行
SIGTSTP 终端停止信号
SIGTOUT 后台进程请求进行写操作
SIGTTIN 后台进程请求进行读操作
示例
kill –l #可以查看linux内核支持的信号
man 7 signal #查看信号的默认动作、信号的含义
信号响应处理
忽略信号
不采取任何操作,但有两个信号不能被忽略:SIGKILL(9号)和SIGSTOP(19)。
思考:为什么进程不能忽略SIGKILL、SIGSTOP信号?
答:如果应用程序可以忽略这2个信号,系统管理无法杀死、暂停进程,无法对系统进行管理;同时SIGKILL和SIGSTOP信号是不能被捕获的。
捕获并处理信号
内核中断正在执行的代码,转去执行先前注册过的处理程序。
执行默认操作
默认操作通常是终止进程,这取决于被发送的信号。
信号的默认操作:通过 man 7 signal 进程查看(同前)
编程实践:让应用程序捕捉Ctrl+C[SIGINT]信号
void onSignalAction(int signalNumber) { switch(signalNumber) { case SIGINT: cout << "Ctrl + C ..." << endl; break; default: cout << "Other Signal ..." << endl; break; } } int main() { signal(SIGINT,onSignalAction); while (true) { sleep(1); } }
signal函数编程实践
SYNOPSIS
#include <signal.h> typedef void (*sighandler_t)(int); sighandler_t signal(int signum, sighandler_t handler);
//signal信号安装函数
作用1:注册一个信号处理函数。
作用2:忽略信号、设置信号默认处理,信号的安装和恢复
参数
signal是一个带signum和handler两个参数的函数,准备捕捉或屏蔽的信号由参数signum给出,接收到指定信号时将要调用的函数由handler给出
handler这个函数必须有一个int类型的参数(即接收到的信号代码),它本身的类型是void
handler也可以是下面两个特殊值:
SIG_IGN 屏蔽该信号 SIG_DFL 恢复默认行为 //定义如下 typedef void (*__sighandler_t) (int); #define SIG_ERR ((__sighandler_t) -1) #define SIG_DFL ((__sighandler_t) 0) #define SIG_IGN ((__sighandler_t) 1)
返回值:
RETURN VALUE
signal() returns the previous value of the signal handler, or SIG_ERR on error. In the event of an error, errno is set to indicate the cause.
//示例1. int main() { //父进程忽略子进程退出,避免僵尸进程的方法之一 //signal(SIGCHLD,SIG_IGN); signal(SIGCHLD,onSignalAction); pid_t pid = fork(); if (pid == -1) { perror("fork error"); return -1; } else if (pid == 0) { sleep(3); cout << "Child Exit..." << endl; exit(0); } pause(); return 0; }
//示例2. void onSignalAction(int signalNumber) { switch(signalNumber) { case SIGINT: cout << "SIGINT = " << signalNumber << endl; break; default: cout << "Other Signal ..." << endl; break; } } int main() { //old保存signal函数的返回值,如果这次成功的话,返回SIG_DFL __sighandler_t old = signal(SIGINT,onSignalAction); if (old == SIG_ERR) { perror("signal error"); return -1; } char c; while ((c = getchar()) != ‘q‘) { pause(); } //如果遇到输入字符q,则终止循环,并恢复SIGINT的处理动作为SIG_DFL signal(SIGINT,old); while (true) { pause(); } return 0; }
信号概述