半生已过

导航

linux高级编程-信号(1)-信号的基本概念

  • 中断的概念

    中断指处理机处理程序运行中出现的紧急事件的整个过程.程序运行过程中,系统外部、系统内部或者现行程序本身若出现紧急事件,处理机立即中止现行程序的运行,

  自动转入相应的处理程序(中断处理函数),待处理完后,再返回原来的程序运行,这整个过程称为程序中断。我举个简单的例子,一个人正在看书,突然有人在敲门,这个

  时候他就要中断看书的动作去开门,等开门的动作完成之后就继续回去看书,这就是一次中断。

  • 信号的概念

     有很多人都说信号是软中断,但它的本质是对中断的一种模拟,为linux提供了一种处理异步事件的方法。      

  • 信号与中断的比较

    相同点:

      都支持异步通信方式

      当检测出有信号或中断请求时,都暂停正在执行的程序而去执行相应的中断处理函数

      中断处理完成之后都会继续执行之前的程序

      信号中断都可以进行屏蔽

    不同点: 

      中断有优先级,而信号没有优先级

      中断处理程序是在内核空间运行的,而信号处理程序是在用户空间运行的

      中断响应一般都是及时的,而信号通常都会延迟

  • 信号的分类

    信号分为可靠信号与不可靠信号,可靠信号又称为实时信号,非可靠信号又称为非实时信号

    不可靠信号主要有以下两个问题

      1. 每次信号处理完之后,就会恢复成默认处理(这个只在早期的unix系统中存在,现在的Linux对信号机制进行了改进,因此,不可靠信号主要是指信号丢失)

      2. 存在信号丢失问题

     在linux系统中的64个信号中,前31个信号都是不可靠信号,后面的都是可靠信号

  • 信号的处理方式

    信号的处理方式有三种,分别是默认处理、忽略处理、自定义处理

    1. 信号的默认处理: 

信号 动作 发生条件
SIGABRT 终止+core 当程序调用abort函数时,会产生该信号,程序异常终止
SIGALRM 终止 当由alarm或setitimer函数设置的定时器超时时,会产生该信号
SIGBUS 终止+core 经常因为内存错误产生该信号
SIGCHLD 忽略 当进程terminate或stopped的时候,该信号会发送给父进程。如果父进程需要知道子进程什么时候终止,父进程必须捕获该信号。通常在该信号的捕获函数中调用wait或waitpid获取子进程的pid和终止状态
SIGCONT 忽略/继续 作业控制命令进程继续执行时,该信号发送给进程。如果进程之前已被停止,则该信号的默认处理方式是继续进程的执行;否则,忽略该信号
SIGFPE 终止+core 当发生算术错误(如:除零,溢出等)时,产生该信号
SIGHUP 终止 当终端界面检测到连接断开时,内核向与控制终端的session leader进程发送该信号(当且仅当终端的CLOCAL标识位没有被设置时,才会发送该信号)。接收信号的session leader可能是后台进程,这与普通终端产生的信号不同,普通终端信号接收者是前台进程组。另外,当控制终端的session leader终止时,SIGHUP信号会发送到前台进程组。因为守护进程没有控制终端,通常不应该接收该信号的,所以这个信号常常被用作守护进程重新读取配置文件的信号
SIGILL 终止 当处理器执行了非法指令时,产生该信号
SIGINT 终止 当向终端输入终端键(Control+C或DELETE)时,终端产生SIGINT信号。该信号被发送到前台进程组。通常用来终止已运行的进程
SIGIO 终止/忽略 该信号用来提供异步IO模式。当有IO可用时,产生该信号通知进程
SIGKILL 终止 该信号给超级用户提供了终止任何进程的能力,通常通过kill函数或命令。该信号不能够被忽略或捕获
SIGPIPE 终止 当向已经关闭读者的管道写数据时,会产生该信号。同样向未连接的SOCK_STREAM类型的socket写数据时,也会产生该信号
SIGPOLL 终止 当指定的事件发生在可选择的设备上时,产生该信号
SIGPROF 终止 由setitimer设置的间隔定时器超时会产生该信号
SIGPWR 终止 当系统有UPS(Uninterruptible Power Supply,即电池)时,断电后使用电池,当电池电量低时,会产生该信号通知进程在1530秒内关闭
SIGQUIT 终止+core 当输入退出键(Control+\)时,终端将会产生SIGQUIT信号,该信号被传送到前台进程组
SIGSEGV 终止+core 非法内存引用时,产生该信号
SIGSTOP 停止进程 作业控制信号,用来停止进程。该信号不能被忽略或捕获
SIGSYS 终止+core 非法系统调用时,产生该信号
SIGTERM 终止 kill函数默认发送的信号,用来终止进程
SIGTRAP 终止+core 系统定义的硬件错误。通常,在遇到调试断点时,将控制权传递给debugger
SIGTSTP 停止进程 当输入挂起键(Control+Z)时,终端产生该(交互式停止)信号停止进程。该信号被发送给前台进程组
SIGTTIN 停止进程 当后台进程组中的进程要求从控制终端读取数据时,会产生该信号。有两个例外情况:1、要求读数据的后台进程忽略或阻塞了该信号,2、进程所属进程组是“孤儿”。在这两种情况下,不会产生该信号,否则,read会错误返回,并将errno设置为EIO
SIGTTOU 停止进程 当后台进程组中的进程要求写数据到控制终端时,会产生该信号。后台进程可以被允许写数据到控制终端。当不允许后台进程写数据到控制终端时,write会错误返回,并将errno设置为EIO。到有两个例外情况:1、要求写数据的后台进程忽略或阻塞了该信号,2、进程所属进程组是“孤儿”。在这两种情况下,不会产生该信号
SIGURG 忽略 当网络连接(Socket)接收到带外数据(out-of-band data)时,会产生该信号
SIGUSR1 终止 用户自定义的信号
SIGUSR2 终止 用户自定义的信号
SIGVTALRM 终止 由setitimer设置的虚拟定时器超时时,产生该信号
SIGXCPU 终止+core/忽略 进程超过了CPU的软限制时,产生该信号
SIGXFSZ 终止+core/忽略 进程超过了文件大小的软限制时,产生该信号

 

    2. 忽略信号

      信号的忽略主要使用signal()函数,如下面代码所示:

1 void ignoreSignal()
2 {
3     // SIG_IGN : ignore signal
4     signal(SIGINT, SIG_IGN);
5     for (;;) {}
6 }

      将忽略的信号重新设置为缺省的处理方式:

1 void defaultSignal()
2 {
3     // SIG_IGN : ignore signal
4     signal(SIGINT, SIG_DFL);
5     for (;;) {}
6 }

    3. 自定义信号处理函数

      信号的自定义处理函数,同样使用signal函数进行注册,代码如下所示:

 1 /**
 2  * @brief handle : User-defined signal processing function
 3  * @param sig
 4  */
 5 void handle(int sig)
 6 {
 7     std::cout << " handle signal ******* " << sig << std::endl;
 8 }
 9 
10 int main(int argc, char *argv[])
11 {
12     if (SIG_ERR == signal(SIGINT, handle)) {
13         return 0;
14     }
15     for (;;) {}
16 }

 

posted on 2021-04-14 20:58  半生已过  阅读(115)  评论(0编辑  收藏  举报