Linux下异常信号

我们介绍一些标准信号的名称以及它们代表的事件。每一个信号名称是一个代表正整数的宏,但是你不要试图去推测宏代表的具体数值,而是直接使用名称。这是因为这个数值会随不同的系统或同样系统的不同版本而不同,但是名称还算是标准化和统一的。
   这些名称定义在signal.h中。
   int NSIG是一个定义的宏,它描述了定义的信号的数量。由于信号的数值是从0开始连续分配的,所以,NSIG比系统中所定义的最大的信号数值大1。

11.2.1 程序出错信号
   下面介绍的信号是有程序的错误造成的。这些严重的错误会被计算机或操作系统检测出来。一般情况下,产生了这种信号表明你的程序遭到严重的破坏,没有办法继续完成产生错误的计算。

很多程序要控制这些信号是要在程序退出前进行一些清理工作。比如,关闭临时文件,清理缓冲区等。程序可以注册一个函数句柄来完成这些工作,然后在让系统执

行缺省的操作来结束进程的执行。终止可能是产生这类错误的程序的最后的操作,但也有例外,比如一些在解释环境中执行的程序,产生错误时需要返回解释环境本
身。
   这类信号的缺省动作就是终止程序的执行。如果你定义了自己的处理,而没有最后调用终止进程,或者阻塞或忽略了该信号,那么你的程序可能会造成极其严重的后果。除非这个信号本身并不是出错产生的,而是通过调用kill函数或raise函数直接通过系统发送的。

当这些信号结束进程时,系统会产生一个内核转储文件,用来记录发生错误退出前程序的状态。内核转储文件的文件名是core,它会被写到当前进程的当前目录

中。在Linux系统中,你也可以通过环境变量COREFILE来设定产生内核转储文件的文件名。产生内核转储文件的目的是帮助你事后利用调试器查明产生
错误的原因。
   下面逐一介绍这类信号的名称:
   int SIGFPE
   这个信号表明产生了一个致命的算术运算错误。尽管该信号的名称来源于“浮点异常(floating-point exception)”,但是,它实际上包含了所有的算术指令错误,包括除数是0和溢出等。
   int SIGILL
  
这个信号的名称来源于“非法的指令(illegal
instrution)”,它往往意味着你的程序要执行根本无法译码的指令或你无权执行的特权指令。既然C语言只能编译产生有效的合法的指令,所以
SIGILL信号很多情况下表明可执行文件破坏了,或者正在把数据当作代码来执行。后一种情况往往是由于把一个指针错当成函数指针传递,或者数组越界破坏
了堆栈段的数据,使其中的函数返回地址错误等。SIGILL也可以由堆栈溢出,或者系统无法执行传递给系统的信号响应函数的句柄引起。
   int SIGSEGV

当程序试图读或写系统分配给它的内存以外的存储器,或者写只有读权限的存储器时会发生这个信号。实际上,由于操作系统检测机制的限制,对程序的检测并不是
那么及时,往往只有当超出范围很远时系统才会检测出来。信号的名称来源于“段变异(segmentation
violation)”。这个信号的发生往往是由于引用没有初始化或空的指针,或者用指针引用数组时由于疏于检查而越界。
   int SIGBUS

这个信号由于引用无效的指针产生。和SIGSEGV相似,典型情况下,它也是由于没有正确初始化指针引起的。它们的区别是,SIGSEGV是用无效的指针

引用了有效的内存地址,而SIGBUS是引用了无效的内存地址。SIGBUS通常的产生是因为没有正确初始化指针变量,比如,指针指向8字节对齐的变量而
引用的地址是奇数。该信号的名称是“总线错误(bus error)”的缩写。
   int SIGABRT
   这个信号是程序调用函数abort()产生的。关于函数abort()的用法,参见前面的有关章节。
   int SIGIOT
   在Linux系统中,它是SIGABRT的另一个名称。
   int SIGTRAP
   该信号是由计算机的断点指令产生的。调试程序使用该信号。当程序执行到设置断点的指令,引起发送该信号,同时调试程序捕获该信号,获得控制权,进行程序的调试。因此,你的程序是无法看到该信号的。
   int SIGEMT
   模拟自陷信号。它是由系统未能实现,必须由软件模拟的指令引起的。截获该信号,并在软件中模拟引起信号的指令的执行。
   int SIGSYS
   错误的系统调用。就是说,程序进行了系统调用,但是传递给系统的调用号是错误的,系统无法完成调用。

11.2.2 程序终止信号
  
这些信号都是用来告诉程序通过某种方式结束。它们之所以有各种不同的名称,是因为它们使用的目的稍有不同,或者程序希望用稍微不同的方式处理它们。虽然这

些信号对程序的后果都是相同的,都是结束程序的执行,但还是有理由处理这些信号。通常是因为程序希望在结束之前能够清理一下,比如,能够纪录下某中状态,
等等。
   缺省的处理(目前)是结束进程的执行。
   int SIGTERM
   该信号是一个最普通的让程序结束的信号。进程可以阻塞、控制和忽略该信号,它是礼貌的要求一个程序结束的普通的方法,比如,通过shell命令kill在缺省情况下就发送该信号结束进程。
   int SIGINT
   该名称是program interrupt的缩写,当用户从控制台输入终止字符(通常是Ctrl-c)时发送给进程的信号。
   int SIGQUIT

该信号和SIGINT相似,区别是它通过用户输入退出字符(通常是Ctrl-/)来产生,进程处理退出外,还要产生内核转储,就象接收到了错误信号一样。

对于这个信号,你可以认为是用户发现了程序错误而通知程序的一种方法。在处理该信号时,某些退出清理最好不要做,这样能够让用户可以通过转储的内核来察看
当时的状态。
   int SIGKILL
  
SIGKILL信号用来让进程立即终止,它不能被控制和忽略,总是致命的,也不能阻塞。该信号通常只能通过特定的命令直接产生,既然它是不可忽略的,你应
该把它作为最后的手段使用,而首先使用不太激烈的手段,如Ctrl-c或者SIGTERM等方法。如果一个进程对其它结束信号没有响应,则采用
SIGKILL信号,总是能让程序结束。事实上,如果SIGKILL信号也不起作用的话,你就应该报告一个内核错误。当一个进程由于某中原因不能在进行下
去的时候,系统也能够发送该消息结束进程的执行。
   int SIGHUP
   SIGHUP信号(hang up)报告用户的终端已经从系统中断开,或者用来作为作业控制的手段。

11.2.3 闹钟信号
   这类信号用来表明定时器激活,信号的缺省行为是让进程结束。虽然这种缺省行为通常是没有什么用处的,但是没有其它的缺省行为可用。因此,往往需要程序用自己的函数控制该类信号的行为。
   int SIGALRM
   该信号被使用实际时间或时钟数的定时器使用,比如,alarm()函数。
   int SIGVTALRM
   该函数被使用当前进程使用的CPU时间的函数使用。
   int SIGPROF
   该信号用来表明当前进程使用的CPU时间和为当前进程服务的系统消耗的CPU时间的综合,一般用来生成代码的简略概括。

11.2.4 异步I/O信号
   这类信号和异步I/O操作有关,你必须通过直接调用fcntl()函数才能使某些文件描述符产生该信号。该信号的缺省动作是忽略该信号的作用。
   int SIGIO
   SIGIO信号是当某个打开的文件描述符已经准备好输入输出时才会发送该信号。在许多系统上,只有终端和套接口才可能发送这个信号,而普通的文件不会发送这个信号。在GNU系统上,任何文件,只要你说明它是异步打开,就可能发送这个信号。
   int SIGURG
   这个信号只用来表示套接口接受到紧急或者带外数据时使用,参看后面的网络编程的部分。
   int SIGPOLL
   系统v的信号,和SIGIO相似,只是为了兼容的目的才设立。

11.2.5 作业控制信号
   这一组信号用来支持作业控制,一般情况下,你可以不用管这些信号,采用系统缺省的行为就可以了,除非你确切知道该怎样控制作业系统的工作。
   int SIGCHLD
   当一个子进程结束时,就会向父进程发送该信号。该信号的缺省行为是忽略,当进程建立起一个处理该信号的函数句柄,并且这是已经有zombie进程存在,那么是否产生该信号由系统决定。
   int SIGCLD
   信号SIGCHLD的旧名称。
   int SIGCONT

这个信号的作用是当进程被停止后使进程继续执行,而不做任何其他的工作。你不能阻塞该信号,但是你可以为该信号设置一个处理函数句柄,它总是使进程无条件

的执行下去。大多数程序没有理由控制该信号,它们只是简单的继续被中断的操作。你可以利用该处理函数的句柄完成一些你需要的特殊工作,比如,重新打印一些
提示信息,如果程序是因为等待输入而被挂起的话。
   int SIGSTOP
   该信号停止一个进程,它不能被控制、忽略和阻塞。
   int SIGTSTP
   这是一个交互式的停止信号。不象SIGSTOP,它可以被控制或忽略。当你从控制台输入SUSP字符(Ctrl-z)时,就会产生该信号。
   int SIGTTIN
   当一个进程在后台执行时,它不能从用户的终端中读入任何输入。当一个后台进程试图从用户终端读时,所有进程都会接受到一个SIGTTIN信号。该信号的缺省操作是停止进程,从而让需要输入的后台进程能够到前台读入需要的输入信息。
   int SIGTTOU
   它和SIGTTIN相似,只是发生在后台进程写终端时。

当一个进程停止时,任何信号都不会再传递给它,除了SIGKILL和SIGCONT信号(显然),所有给它的信号标记为未定的(pending),并且只

有当进程重新进入执行状态时才得到最终传递。SIGKILL信号总是迫使进程结束,而且不能阻塞、忽略和控制。你可以忽略SIGCONT信号,但是它总是
能够使被停止的进程继续执行。一个SIGCONT信号可以让所有未定的停止信号被丢弃,类似的,一个停止信号能让未定的SIGCONT信号丢弃。

11.2.6 操作错误信号
   这组信号都是由进程的操作错误引起的,他们不必是程序的错误,而是任何阻止操作完成的错误。这些信号的缺省操作是中止进程的执行。
   int SIGPIPE

如果你使用管道或者FIFO进行进程间的通讯,你必须让你的应用程序在写入一个管道之前先有一个程序已经打开了该管道并且已经开始读取数据。如果这时没有

开始,或者读管道的进程意外退出了,那么写操作就会产生一个SIGPIPE信号。如果SIGPIPE信号被阻塞、控制或忽略,那么写操作将返回错误,错误
代码是EPIPE。更进一步的信息参见后面的相关章节。
   int SIGLOST
   该信号表明资源的丢失,在GNU系统中,通常任何提供服务的服务器意外死机,都能引起该信号。一般忽略该信号并无不妥,因为和这种操作相关的错误都能使相关函数返回错误。
   int SIGXCPU
   CPU时间限制到。该信号表明对进程使用的CPU时间的限制已经达到。
   int SIGXFSZ
   该信号表明进程试图增长文件超过系统对文件长度的限制。

11.2.7 外围信号
   这组信号用于各种各样的目的,一般不会影响进程的执行。
   int SIGUSR1
   int SIGUSR2
   这两个信号可以用来完成你希望的任何目的,通常用来进行网络通讯。如果你在一个进程里有用来接受该信号的程序,你的另外的进程就可以发送信号给相应的进程。这个信号的缺省操作是终止进程的执行。
   int SIGWINCH
   系统终端的每屏行数和列数发生改变时发送该信号。它的缺省操作是忽略。如果是一个全屏幕输出的程序则需要控制该信号,根据新的每屏行和列数重新初始化输出。
   int SIGINFO
   该信号可以由控制台通过键盘发送给所有前台进程组的进程。如果接收信号的进程是领头进程,那么它一般会打印一些系统信息和进程的一些当前信息,如果是其他进程,那么缺省情况下不会做任何事情。

11.2.7 信号消息
   我们上面提到的标准信号都可以用一个系统提供的字符串描述。我们用函数strsignal()和psignal()来获取相关的字符串。
   char * strsignal(int signum)

该函数返回一个已经分配好的静态字符串,用来描述signum信号相关的文字信息。你无权修改这个返回的字符串,并且,既然在另外的调用中能够重写该字符
串,如果你需要在后面的程序中使用,必须自己保存该字符串的备份。该函数是GNU系统的扩充,它的原型包含在string.h头文件中。
   void psignal(int signum, const char *message)

该函数输出一个描述signum信号的消息到标准错误输出。如果传递该函数的message是一个NULL指针或空串,这个函数只打印和信号相关的标准的
消息。如果你传递给函数非空的message参数,那么系统会先输出message字符串,然后输出相关消息。该函数在signal.h文件中声明。

Linux下异常信号

时间: 2024-10-08 20:27:28

Linux下异常信号的相关文章

linux下的信号屏蔽字

信号的表示 我们知道linux下,可以通过kill命令向进程发送信号. 当进程收到信号,执行处理动作被称为递达; 当进程接收到信号,还未来得及处理被称之为未决(pending); 进程可以选择阻塞某个信号,当某个信号被阻塞(block)时,永远不会递达! 因此,与这三种处理相对应,在进程的pcb中,存在三张位图来描述信号相关信息! block.pending与handler block是一个位图,如果某个信号block为1,则表示其永远也不会递达,也就是说永远都不会执行handler表中的函数.

linux下 signal信号机制的透彻分析与各种实例讲解

转自:http://blog.sina.com.cn/s/blog_636a55070101vs2d.html 转自:http://blog.csdn.net/tiany524/article/details/17048069 首先感谢上述两位博主的详细讲解. 虽然内容有点长,但是分析的很全面,各种实例应用基本都考虑到了. 本文将从以下几个方面来阐述信号: (1)信号的基本知识 (2)信号生命周期与处理过程分析 (3) 基本的信号处理函数 (4) 保护临界区不被中断 (5) 信号的继承与执行 (

Linux下捕捉信号

关于 信号signal的知识铺垫 点这里 信号由三种处理方式: 忽略 执行该信号的默认处理动作 捕捉信号 如果信号的处理动作是用户自定义函数,在信号递达时就调用这个自定义函数,这称为捕捉信号. 进程收到一个信号后不会被立即处理,而是在恰当时机进行处理!即内核态返回用户态之前 ! 但是由于信号处理函数的代码在用户空间,所以这增加了内核处理信号捕捉的复杂度. 内核实现信号捕捉的步骤: 用户为某信号注册一个信号处理函数sighandler. 当前正在执行主程序,这时候因为中断.异常或系统调用进入内核态

辛星浅析Linux中的信号

要说Linux中的信号,不得不先提一下中断这个概念.中断是系统中对于异步事件的响应,也就是说某个进程可以在代码执行的过程中被打断了,它先去执行一段异常处理程序.中断可以分为硬件中断,也就是外部中断,它是由外部设备通过硬件请求的方式产生的中断.而软件中断,也就是内部中断,它是由CPU运行程序的一些错误或者执行内部程序调用的时候引起的一种中断. 在CPU的层面去看中断,是这样的一个步骤: ①中断源发出中断信号  ②CPU判断是屏蔽该中断以及现场保护③CPU查询中断向量表,找到相应服务程序的入口地址,

linux 下C/C++程序常用调试方法(gdb)

 不管是在开发或者运行过程中,调试保证程序正常运行最基本的手段,熟悉这些调试方式,方便我们更快的定位程序问题所在,提高开发效率. 一 程序正常运行调试 (1)  直接使用gdb 开发过程中最常用的方式,我们可以在其过程中给程序添加断点,监视等辅助手段,监控其行为是否与我们设计相符,比如: (2)      程序已经运行,通过attach附加到进程 二 程序中断后调试 首先简单介绍下linux 下的信号: 软中断信号(signal,又简称为信号)用来通知进程发生了异步事件.进程之间可以互相通过

linux下常见内存异常查证工具和方法介绍

linux下常见内存异常查证工具和方法介绍 内存异常导致的异常往往很难查证,本文介绍在linux下的各种常见内存异常的查证工具和方法. 1.访问空指针/未初始化指针 这个是最简单的内存异常了,只要能够生成coredump文件,可以快速定位问题代码. 开启coredump 部分环境下默认不会生成coredump,需要运行如下命令:ulimit -c unlimited //unlimited表示不限制coredump文件大小,也可以指定一个最大文件大小. 定制core文件名 默认的coredump

Linux下信号

信号和 中断是很类似的,只不过是一个是硬件中断,另外一个是软中断.中断是系统对于异步事件的响应. 简单理解就是:中断源 发出 中断信号 在 中断向量表 中执行 中断处理程序 之前保存 现场信息 异步事件的响应:进程执行代码的过程中可以随时被打断,然后去执行异常处理程序. 中断源发出中断信号,CPU判断中断是否屏蔽屏蔽.保护现场 ,cpu执行中断处理程序, cpu恢复现场,继续原来的任务. 中断向量表保存了中断处理程序的入口地址. 中断个数固定,操作系统启动时初始化中断向量表. 中断有优先级,中断

linux下的常见信号总结

在linux下有很多信号,按可靠性分为可靠信号和非可靠信号,按时间分为实时信号和非实时信号,linux进程也有三种方式来处理收到的信号: (1)忽略信号,即对信号不做任何处理,其中,有两个信号不能忽略:SIGKILL及SIGSTOP: (2)捕捉信号.定义信号处理函数,当信号发生时,执行相应的处理函数: (3)执行缺省操作,Linux对每种信号都规定了默认操作. Linux进程对实时信号的缺省反应是进程终止.但是对于高性能服务器编程来说,这是致命的缺陷,对于这类服务器需要保证在收到各种信号后仍然

TCP系列36—窗口管理&流控—10、linux下的异常报文系列接收

在这篇文章中我们看一下server端在接收到异常数据系列时的处理,主要目的是通过wireshark示例对这些异常数据系列的处理有一个直观的认识,感兴趣的自行阅读相关代码和协议,这里不再进行详细介绍 在进行下面的测试前,首先如下设置相关的参数,其中window参数指定了到127.0.0.2的tcp连接的最大接收窗口. [email protected]:/home/******/tcp12# ip route change local 127.0.0.2 dev lo window 40 一.wi