08_中断的概念及信号的基本概念

中断
   中断是系统对于异步事件的响应
   中断信号
   中断源
   现场信息
   中断处理程序
   中断向量表
异步事件的响应:进程执行代码的过程中可以随时被打断,然后去执行异常处理程序
生活中的中断和计算机系统中的中断
1)  无中断生活场景
张三看书,厨房烧水
2)有中断的生活场景
张三看书,设置闹钟,厨房烧水。
闹钟发出中断信号,张三把书合好(第20页),去厨房把开水事情处理好,张三重新打开20页进行阅读。
3)计算机系统的中断场景
中断源发出中断信号,CPU判断中断是否屏蔽、保护现场 ,cpu执行中断处理程序, cpu恢复现场,继续原来的任务。
4)中断的其他概念
中断向量表保存了中断处理程序的入口地址。
中断个数固定,操作系统启动时初始化中断向量表。
中断有优先级(有人敲门,有人打电话,有优先级)
中断可以屏蔽(张三可以屏蔽电话)。
中断分类
   硬件中断(外部中断)
    外部中断是指由外部设备通过硬件请求的方式产生的中断,也称为硬件中断
   软件中断(内部中断)
    内部中断是由CPU运行程序错误或执行内部程序调用引起的一种中断,也称为软件中断。
   x86平台INT指令 ARM软中断指令SWI

信号概念
   信号是UNIX系统响应某些状况而产生的事件,进程在接收到信号时会采取相应的行动。
   信号是因为某些错误条件而产生的,比如内存段冲突、浮点处理器错误或者非法指令等
   信号是在软件层次上对中断的一种模拟,所以通常把它称为是软中断

信号和中断的区别(重点)
   信号与中断的相似点:
   (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。
思考1:为什么进程不能忽略SIGKILL、SIGSTOP信号。(如果应用程序可以忽略这2个信号,系统管理无法杀死、暂停进程,无法对系统进行管理。)SIGKILL(9号信号)和SIGSTOP信号是不能被捕获的。
   捕获并处理信号   
    内核中断正在执行的代码,转去执行先前注册过的处理程序。
   执行默认操作   
    默认操作通常是终止进程,这取决于被发送的信号。
信号的默认操作:通过 man 7 signal 进程查看
SIGHUP        1       Term    Hangup detected on controlling terminal
                                     or death of controlling process
       SIGINT        2       Term    Interrupt from keyboard
       SIGQUIT       3       Core    Quit from keyboard
       SIGILL        4       Core    Illegal Instruction
       SIGABRT       6       Core    Abort signal from abort(3)
       SIGFPE        8       Core    Floating point exception
       SIGKILL       9       Term    Kill signal
       SIGSEGV      11       Core    Invalid memory reference
       SIGPIPE      13       Term    Broken pipe: write to pipe with no
                                     readers
       SIGALRM      14       Term    Timer signal from alarm(2)
       SIGTERM      15       Term    Termination signal
       SIGUSR1   30,10,16    Term    User-defined signal 1
       SIGUSR2   31,12,17    Term    User-defined signal 2
       SIGCHLD   20,17,18    Ign     Child stopped or terminated
       SIGCONT   19,18,25    Cont    Continue if stopped
       SIGSTOP   17,19,23    Stop    Stop process
       SIGTSTP   18,20,24    Stop    Stop typed at terminal
       SIGTTIN   21,21,26    Stop    Terminal input for background process
       SIGTTOU   22,22,27    Stop    Terminal output for background process

       The signals SIGKILL and SIGSTOP cannot be caught, blocked, or ignored.

信号signal函数编程实践

signal信号安装函数
signal函数,作用1:站在应用程序的角度,注册一个信号处理函数。
           作用2:忽略信号、设置信号默认处理  信号的安装和恢复
   typedef void (*__sighandler_t) (int);
   #define SIG_ERR ((__sighandler_t) -1)#define SIG_DFL ((__sighandler_t) 0)#define SIG_IGN ((__sighandler_t) 1)
   函数原型:
    __sighandler_t signal(int signum, __sighandler_t handler);
   参数
   signal是一个带signum和handler两个参数的函数,准备捕捉或屏蔽的信号由参数signum给出,接收到指定信号时将要调用的函数由handler给出
   handler这个函数必须有一个int类型的参数(即接收到的信号代码),它本身的类型是void
   handler也可以是下面两个特殊值:
                   SIG_IGN  屏蔽该信号
                   SIG_DFL  恢复默认行为
#include <sys/types.h>
#include <unistd.h>
#include <signal.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <errno.h>
#include <signal.h>

//信号的注册
#if 0
//信号处理函数
void handler(int num)
{
    printf("recv num:%d \n", num);  
    if (num == SIGQUIT)
    {
        exit(0);//屏蔽后程序不会退出的!
    }else if(num == SIGUSR1){
        printf("recive SIGUSR1\n"); 
    }else if(num == SIGUSR2){
        printf("recive SIGUSR2\n"); 
    }
}

void test()
{
    //注册一个信号
    //SIGINT  是ctrl+c 会产生2号信号。。。 中断应用程序
    if(SIG_ERR == signal(SIGINT, handler)){
        perror("signal()"); 
    }

    if(SIG_ERR == signal(SIGQUIT, handler)){
        perror("signal()"); 
    }

    if(SIG_ERR == signal(SIGUSR1, handler)){//这是用户定义的信号,官方定义
        perror("signal()"); 
    }

    if(SIG_ERR == signal(SIGUSR2, handler)){
        perror("signal()"); 
    }

    while(1)
    {
        /*
            pause()函数
       将进程置为可中断睡眠状态。然后它调用内核函数schedule(),
            使linux进程调度器找到另一个进程来运行。
       
          pause使调用者进程挂起,直到一个信号被捕获
          pause()使调用进程挂起直至捕捉到一个信号
          只有执行了一个信号处理程序并从其返回时,pause()才返回。
          这种情况下,pause 返回-1 ,errno 置为EINTR
        */

        printf(" pause() 返回值为 %d\n", pause());
        printf("使用strerror--%s\n", strerror(errno));
        perror("使用perror--pause()");
    }
}
/*
 kill -USR2 3521

    recive SIGUSR2
    pause() 返回值为 -1
    使用strerror--Interrupted system call
    使用perror--pause(): Interrupted system call
*/
#endif

//信号的安装与恢复
// sighandler_t signal(int signum, sighandler_t handler);
//函数的返回值是以前的信号处理配置
#if 1
void handler(int num)
{
    printf("recv num:%d \n", num);  
    if (num == SIGQUIT)
            exit(0);//屏蔽后程序不会退出的!
}

void test()
{
     __sighandler_t  oldHandle;

     oldHandle = signal(SIGINT, handler);
    if(oldHandle == SIG_ERR){
        perror("signal()"); 
        return;
    }
    printf("if enter a, reset signal\n");
    while(getchar() != 'a'){
        ;   
    }

    //方法1
    #if 0
    //键入a后,恢复默认函数
    if( SIG_ERR == signal(SIGINT, oldHandle)){
        perror("func signal err");
        return ;
    }

    #else
    //方法2
        if( SIG_ERR == signal(SIGINT, SIG_DFL)){
        perror("func signal err");
        return ;
    }
    #endif
}
#endif


int main()
{
    test();
    while(1);
    return 0;   
}
/*
运行结果
    if enter a, reset signal
    ^Crecv num:2 
    ^Crecv num:2 
    a
    ^C
*/

猜你喜欢

转载自blog.csdn.net/WUZHU2017/article/details/81868252