十四、Linux系统编程-信号(一)中断、信号、中断和信号

一、中断
(1)、中断概念
      中断是用以提高计算机工作效率、增强计算机功能的一项重要技术。最初引入硬件中断,只是出于性能上的考量。如果计算机系统没有中断,则处理器与外部设备通信时,它必须在向该设备发出指令后进行忙等待(Busy waiting),反复轮询该设备是否完成了动作并返回结果。这就造成了大量处理器周期被浪费。引入中断以后,当处理器发出设备请求后就可以立即返回以处理其他任务,而当设备完成动作后,发送中断信号给处理器,后者就可以再回过头获取处理结果。这样,在设备进行处理的周期内,处理器可以执行其他一些有意义的工作,而只付出一些很小的切换所引发的时间代价。后来被用于CPU外部与内部紧急事件的处理、机器故障的处理、时间控制等多个方面,并产生通过软件方式进入中断处理(软中断)的概念。

硬件中断(Hardware Interrupt):

  • 可屏蔽中断(maskable interrupt)。硬件中断的一类,可通过在中断屏蔽寄存器中设定位掩码来关闭。
  • 非可屏蔽中断(non-maskable interrupt,NMI)。硬件中断的一类,无法通过在中断屏蔽寄存器中设定位掩码来关闭。典型例子是时钟中断(一个硬件时钟以恒定频率—如50Hz—发出的中断)。
  • 处理器间中断(interprocessor interrupt)。一种特殊的硬件中断。由处理器发出,被其它处理器接收。仅见于多处理器系统,以便于处理器间通信或同步。
  • 伪中断(spurious interrupt)。一类不希望被产生的硬件中断。发生的原因有很多种,如中断线路上电气信号异常,或是中断请求设备本身有问题。

软件中断(Software Interrupt):

  • 软件中断。是一条CPU指令,用以自陷一个中断。由于软中断指令通常要运行一个切换CPU至内核态(Kernel Mode/Ring 0)的子例程,它常被用作实现系统调用(System call)。

处理器通常含有一个内部中断屏蔽位,并允许通过软件来设定。一旦被设定,所有外部中断都将被系统忽略。

中断处理的一般步骤中断源->判断中断屏蔽->保护现场->从中断向量表查找并调用中断处理程序->恢复现场

二、信号
        在计算机科学中,信号英语:Signals)是Unix类Unix以及其他POSIX兼容的操作系统中进程间通讯的一种有限制的方式。它是一种异步的通知机制,用来提醒进程一个事件已经发生。当一个信号发送给一个进程,操作系统中断了进程正常的控制流程,此时,任何非原子操作都将被中断。如果进程定义了信号的处理函数,那么它将被执行,否则就执行默认的处理函数。

(1)、信号发送
  • 在一个运行的程序的控制终端键入特定的组合键可以向它发送某些信号:
    • Ctrl-C发送INT信号(SIGINT);默认情况下,这会导致进程终止。
    • Ctrl-Z发送TSTP信号(SIGTSTP);默认情况下,这会导致进程挂起。
    • Ctrl-\发送QUIT信号(SIGQUIT);默认情况下,这会导致进程终止并且将内存中的信息转储到硬盘(核心转储)。
    • (这些组合键可以通过stty命令来修改。)
  • kill()系统调用会在权限允许的情况下向进程发送特定的信号,类似地,kill命令允许用户向进程发送信号。raise(3)库函数可以将特定信号发送给当前进程。
  • 像除数为零、段错误这些异常也会产生信号(这里分别是SIGFPE和SIGSEGV,默认都会导致进程终止和核心转储).
  • 内核可以向进程发送信号以告知它一个事件发生了。例如当进程将数据写入一个已经被关闭的管道是将会收到SIGPIPE信号,默认情况下会使进程关闭。
(2)、信号处理
信号处理函数可以通过signal()系统调用来设置。如果没有为一个信号设置对应的处理函数,就会使用默认的处理函数,否则信号就被进程截获并调用相应的处理函数。在没有处理函数的情况下,程序可以指定两种行为:忽略这个信号(SIG_IGN)或者用默认的处理函数(SIG_DFL)。但是有两个信号是无法被截获并处理的:SIGKILLSIGSTOP
注意:因为竞态条件的存在,信号的处理是有弱点的。因为信号是异步的,所以在处理一个信号的过程中,进程可能收到另一个信号(甚至是相同的信号)。sigprocmask()系统调用可以用来阻塞和恢复信号的传递。信号可以造成进程中系统调用的中断,并在信号处理完后重新开始未完成的系统调用。信号处理函数应该没有任何不想要的副作用,比如,errno的改变、信号掩码的改变、信号处理方法的改变,以及其他全局进程性质的改变。在信号处理函数内使用不可重入函数,如mallocprintf,也是不安全的。
(3)、信号名称
十四、Linux系统编程-信号(一)中断、信号、中断和信号_第1张图片
十四、Linux系统编程-信号(一)中断、信号、中断和信号_第2张图片

三、信号与中断
信号和中断之间的相同和不同点:
(1)、信号与中断的相似点:
  • 采用了相同的异步通信方式;
  • 当检测出有信号或中断请求时,都暂停正在执行的程序而转去执行相应的处理程序;
  • 都在处理完毕后返回到原来的断点;
  • 对信号或中断都可进行屏蔽。
(2)、信号与中断的区别:
  • 中断有优先级,而信号没有优先级,所有的信号都是平等的;
  • 信号处理程序是在用户态下运行的,而中断处理程序是在核心态下运行;
  • 中断响应是及时的,而信号响应通常都有较大的时间延迟。
四、signal
函数声明:
#include 
typedef void (*sighandler_t)(int);
sighandler_t signal(int signum, sighandler_t handler);
函数参数:信号代码,信号处理程序
返回值:成功返回原来的信号处理函数,错误返回SIG_ERR并设置errno

示例:
#include 
#include 
#include 

#include 
#include 
#include 
#include 
#include 
#include 
#define ERR_EXIT(m) \
        do \
        { \
                perror(m); \
                exit(EXIT_FAILURE); \
        }while(0)
void handle(int sig);
int main(int argc,char* argv[])
{
        __sighandler_t oldhandler;
        if ( (oldhandler = signal(SIGINT,handle) ) == SIG_ERR)
                ERR_EXIT("signal error");
        char ch;
        for(;;)
        {
                ch = getchar();
                if (ch == 'o')
                        signal(SIGINT,oldhandler);
        }
        return 0;
}

void handle(int sig)
{
        printf("recv a sig=%d\n",sig);
}

你可能感兴趣的:(Linux系统编程)