1基本概念
中断 q 中断是系统对于异步事件的响应 q 中断信号 q 中断源 q 现场信息 q 中断处理程序 q 中断向量表 异步事件的响应:进程执行代码的过程中可以随时被打断,然后去执行异常处理程序 生活中的中断和计算机系统中的中断 1) 无中断生活场景 张三看书,厨房烧水 2)有中断的生活场景 张三看书,设置闹钟,厨房烧水。 闹钟发出中断信号,张三把书合好(第20页),去厨房把开水事情处理好,张三重新打开20页进行阅读。 3)计算机系统的中断场景 中断源发出中断信号,CPU判断中断是否屏蔽屏蔽、保护现场 ,cpu执行中断处理程序, cpu恢复现场,继续原来的任务。 中断向量表保存了中断处理程序的入口地址。 中断个数固定,操作系统启动时初始化中断向量表。 中断有优先级(有人敲门,有人打电话,有优先级) 中断可以屏蔽(张三可以屏蔽电话)。 |
中断分类 q 硬件中断(外部中断) 外部中断是指由外部设备通过硬件请求的方式产生的中断,也称为硬件中断 q 软件中断(内部中断) 内部中断是由CPU运行程序错误或执行内部程序调用引起的一种中断,也称为软件中断。 q x86平台INT指令 ARM软中断指令SWI |
信号概念 |
q 信号是UNIX系统响应某些状况而产生的事件,进程在接收到信号时会采取相应的行动。 q 信号是因为某些错误条件而产生的,比如内存段冲突、浮点处理器错误或者非法指令等 q 信号是在软件层次上对中断的一种模拟,所以通常把它称为是软中断
|
信号和中断的区别 q 信号与中断的相似点: q (1)采用了相同的异步通信方式; q (2)当检测出有信号或中断请求时,都暂停正在执行的程序而转去执行相应的处理程序; q (3)都在处理完毕后返回到原来的断点; q (4)对信号或中断都可进行屏蔽。 q 信号与中断的区别: q (1)中断有优先级,而信号没有优先级,所有的信号都是平等的; q (2)信号处理程序是在用户态下运行的,而中断处理程序是在核心态下运行; q (3)中断响应是及时的,而信号响应通常都有较大的时间延迟。
|
2信号名称及常用信号
信号名称 描述 SIGABRT 进程停止运行 6 SIGALRM 警告钟 SIGFPE 算述运算例外 SIGHUP 系统挂断 SIGILL 非法指令 SIGINT 终端中断 2 SIGKILL 停止进程(此信号不能被忽略或捕获) SIGPIPE 向没有读者的管道写入数据 SIGSEGV 无效内存段访问
SIGQUIT 终端退出 3 SIGTERM 终止 SIGUSR1 用户定义信号1 SIGUSR2 用户定义信号2 SIGCHLD 子进程已经停止或退出 SIGCONT 如果被停止则继续执行 SIGSTOP 停止执行 SIGTSTP 终端停止信号 SIGTOUT 后台进程请求进行写操作 SIGTTIN 后台进程请求进行读操作
|
实验1: kill –l 可以查看linux内核支持的信号 Man 7 signal 查看信号的默认动作、信号的含义 |
3信号处理
进程对信号的三种相应 q 忽略信号 不采取任何操作、有两个信号不能被忽略:SIGKILL(9号信号)和SIGSTOP。 思考1:为什么进程不能忽略SIGKILL、SIGSTOP信号。(如果应用程序可以忽略这2个信号,系统管理无法杀死、暂停进程,无法对系统进行管理。)。SIGKILL(9号信号)和SIGSTOP信号是不能被捕获的。 q 捕获并处理信号 内核中断正在执行的代码,转去执行先前注册过的处理程序。 q 执行默认操作 默认操作通常是终止进程,这取决于被发送的信号。 信号的默认操作:通过 man 7 signal 进程查看 |
man 7 signal
|
编程实践:让应用程序捕捉ctrl+c信号 以ctrl+c 会产生一个中断。当前应用程序捕捉ctrl+c中断信号。 |
4信号signal函数编程实践
signal信号安装函数
signal函数,作用1:站在应用程序的角度,注册一个信号处理函数。 作用2:忽略信号、设置信号默认处理 信号的安装和恢复 q typedef void (*__sighandler_t) (int); q #define SIG_ERR ((__sighandler_t) -1) q #define SIG_DFL ((__sighandler_t) 0) q #define SIG_IGN ((__sighandler_t) 1) q 函数原型: __sighandler_t signal(int signum, __sighandler_t handler); q 参数 q signal是一个带signum和handler两个参数的函数,准备捕捉或屏蔽的信号由参数signum给出,接收到指定信号时将要调用的函数由handler给出 q handler这个函数必须有一个int类型的参数(即接收到的信号代码),它本身的类型是void q handler也可以是下面两个特殊值: SIG_IGN 屏蔽该信号 SIG_DFL 恢复默认行为 |
#include<stdio.h> #include<stdlib.h> #include<string.h> #include <unistd.h> #include<errno.h> #include <sys/types.h> #include <sys/wait.h> #include <signal.h> /* typedef void (*sighandler_t)(int); sighandler_t signal(int signum, sighandler_t handler); */ int g_tag = 1; __sighandler_t old; // Linux内核调用这个函数 void myhandle(int num) { printf("recv signal id num : %d\n", num); if (3 == num) { g_tag = 0;
// signal(SIGINT, SIG_DFL);
// signal(SIGINT, old); } return; } int main(void) { // 信号的安装 old = signal(SIGINT, myhandle) if ( signal(SIGINT, myhandle) == SIG_ERR ) { perror("signal err"); return 0; } if ( signal(SIGQUIT, myhandle) == SIG_ERR ) { perror("signal err"); return 0; } /* 无效的参数 if ( signal(SIGKILL, myhandle) == SIG_ERR ) { perror("signal err"); return 0; } */ while(g_tag); return 0; }