首页 > 代码库 > 信号概述

信号概述

中断概念

    中断是系统对于异步事件的响应

    中断信号

    中断源

    现场信息

    中断处理程序

    中断向量表

 

异步事件的响应:进程执行代码的过程中可以随时被打断,然后去执行异常处理程序

 

生活中的中断和计算机系统中的中断

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;
}


信号概述