什么是中断?
在计算机科学中,中断是指由于接收到外围硬件(相对于CPU与内存而言)的异步信号或者来自软件的同步信号而进行相应的硬件/软件处理。
硬中断?
显然,外围硬件发给CPU或者内存的异步信号就是硬中断信号。简言之:外设对CPU的中断
软中断?
由软件本身发给内核的中断信号,称之为软中断。通常是由硬中断处理程序或进程调度程序对操作系统内核的中断,也就是我们常说的系统调用(System Call)了。
硬中断与软中断之区别与联系
- 硬中断是有外设硬件发出的,需要有中断控制器之参与。其过程是外设侦测到变化,告知中断控制器,中断控制器通过CPU或内存的中断脚通知CPU,然后硬件进行程序计数器及堆栈寄存器之现场保存工作(引发上下文切换),并根据中断向量调用硬中断处理程序进行中断处理。
- 软中断则通常是由硬中断处理程序或者进程调度程序等软件程序发出的中断信号,无需中断控制器之参与,直接以一个CPU指令之形式指示CPU进行程序计数器及堆栈寄存器之现场保存工作(亦会引发上下文切换),并调用相应的软中断处理程序进行中断处理(即我们通常所言之系统调用)。
- 硬中断直接以硬件的方式引发,处理速度快。软中断以软件指令之方式适合于对响应速度要求不是特别严格的场景。
- 硬中断通过设置CPU的屏蔽位可进行屏蔽,软中断则由于是指令之方式给出,不能屏蔽。
- 硬中断发生后,通常会在硬中断处理程序中调用一个软中断来进行后续工作的处理。
- 硬中断和软中断均会引起上下文切换(进程/线程之切换),进程切换的过程是差不多的。
信号
信号是实现软中断的,不同的操作系统实现的信号不同。在mac中,信号的定义在如下文件中:
每次CTL+C 产生中断信号,CTL+Z可以中断任务,跳出该死循环
终止+core文件
在一个进程异常终止时,在一定的条件下,会在当前工作目录下生成一个core文件。
core文件是该进程(异常终止时)的内存映像(同时加上调试信息)。大多数调试程序都使用 core 文件以检查进程终止时的状态。
信号处理流程
unix 信号处理方式
1、忽略信号:sigkill和sigstop不可行
2、捕获信号:用户捕获信号,执行自己的操作
3、执行系统默认操作:信号发生时系统默认的操作
可靠信号和不可靠信号
在早期的UNIX中信号是不可靠的,不可靠在这里指的是:信号可能丢失,一个信号发生了,但进程却可能一直不知道这一点。
现在 在SIGRTMIN实时信号之前的都叫不可靠信号,这里的不可靠主要是不支持信号队列,就是当多个信号发生在进程中的时候(收到信号的速度超过进程处理的速度的时候),这些没来的及处理的信号就会被丢掉,仅仅留下一个信号。
可靠信号是多个信号发送到进程的时候(收到信号的速度超过进程处理信号的速度的时候),这些没来的及处理的信号就会排入进程的队列。等进程有机会来处理的时候,依次再处理,信号不丢失。
信号在内核中的表示:
信号递达delivery:实际执行信号处理信号的动作
信号未决pending:信号从产生到抵达之间的状态,信号产生了但是未处理
忽略:抵达之后的一种 动作
阻塞block:收到信号不立即处理被阻塞的信号将保持未决状态,直到进程解除对此信号的阻塞,才执行抵达动作
信号产生和阻塞没有直接关系 抵达和解除阻塞没有直接关系!
进程收到一个信号后,不会立即处理,它会在恰当的时机被处理。
中断的系统调用
如果进程在执行一个低速系统调用而阻塞期间捕捉到一个信号,该系统调用就被终端不再继续执行。该系统调用返回出错,其errno被设置为EINTR。现在操作系统引入了某些中断系统调用的自动重启动:自动重启动的系统调用包括:ioctl,read,readv,write,writev,wait和waitpid。其中前5个函数只有对低速设备进行操作时才会被信号终端。而wait和waitpid在捕捉到信号时总是被终端。
可重入函数
用于多任务环境中,一个可重入的函数简单来说就是可以被中断的函数,也就是说,可以在这个函数执行的任何时刻中断它,转入OS调度下去执行另外一段代码,而返![Uploading 捕获_303775.PNG . . .]
回控制时不会出现什么错误;而不可重入的函数由于使用了一些系统资源,比如全局变量区,中断向量表等,所以它如果被中断的话,可能会出现问题,这类函数是不能运行在多任务环境下的。
编写可重入函数时,若使用全局变量,则应通过关中断、信号量(即P、V操作)等手段对其加以保护。
signaction
int sigaction(int sig, const struct sigaction *act, struct sigaction *oact);
stuct sigaction
{
void (*)(int) sa_handle;
sigset_t sa_mask;
int sa_flags;
}
- 阻塞,sigaction函数有阻塞的功能,比如SIGINT信号来了,进入信号处理函数,默认情况下,在信号处理函数未完成之前,如果又来了一个SIGINT信号,其将被阻塞,只有信号处理函数处理完毕,才会对后来的SIGINT再进行处理,同时后续无论来多少个SIGINT,仅处理一个SIGINT,sigaction会对后续SIGINT进行排队合并处理。
- sa_mask,信号屏蔽集,可以通过函数sigemptyset/sigaddset等来清空和增加需要屏蔽的信号,上面代码中,对信号SIGINT处理时,如果来信号SIGQUIT,其将被屏蔽,但是如果在处理SIGQUIT,来了SIGINT,则首先处理SIGINT,然后接着处理SIGQUIT。
- sa_flags如果取值为0,则表示默认行为。还可以取如下俩值,但是我没觉得这俩值有啥用。
SA_NODEFER,如果设置来该标志,则不进行当前处理信号到阻塞
SA_RESETHAND,如果设置来该标志,则处理完当前信号后,将信号处理函数设置为SIG_DFL行为