信号

来源:互联网 发布:跟兄弟连学php 购买 编辑:程序博客网 时间:2024/06/09 20:59

      程序常常在运行时会遇到并不是因为程序运行本身所引发的事件,比如说用户突然中断了程序的运行,因此程序也不得不终止,但是有一部分已经计算好的结果不想丢弃这样就需要在程序退出时保存这些数据,因此程序必须对此类事件做出反映。虽然他并没有办法预测这种情况会在什么时候发生。

      信号就是用于这种目的的,信号是一种事件,他可能与程序异步发生,也就是说不与程序执行过程中的任何事件有联系,如果程序并没有安排怎样处理一个特定的信号,那么当这个信号发生时,程序就会做出一个缺省的反应,标准并没有定义这个缺省的反应是什么,但是大多数情况就是终止程序的运行。另外程序可以调用signal函数或者忽略这个信号,或者设备一个信号处理函数,当信号发生时,函数就调用这个函数。

      常见的信号含义

SIGABRT                   程序请求异常终止

 

SIGFPE                     发生一个算术错误

 

SIGILL                      检测到非法指令

 

SIGSEGV                  检测到对内存的非法访问

 

SIGINT                     收到一个交互性注意信号

 

SIGTERM                  收到一个终止程序的信号

 

raise函数用于显示的引发一个信号,原型如下:

int  raise( int sig );

调用这个函数将引发的他的参数所指定的信号。

当信号发生时调用signal函数可以实现对信号的自定义处理。原型如下:

void  (*signal( int sig, void  (*handler ) ( int ) )  ) (int );

这个函数看起来很复杂,通过前面介绍的分析方法可以知道:

void   ( *signal() ) (int);

signal是一个函数这个函数返回一个指针,这个指针指向一个函数,这个函数没有返回值,这个函数接受一个整型参数。

接下来我们分析signal函数本身:

signal(  int  sig, void  (*handler)( int ) );

signa函数有两个参数,第一个参数是上面所列的信号,第二个参数是我们希望为这个信号设备的信号处理函数,这个处理函数是一个函数指针,它所接受是一个整型参数且没有返回值。当信号发送时,信号代码作为参数传递给信号处理函数

 

信号处理函数的处理过程

当一个已经设置了信号处理函数的信号发生时,系统首先恢复对该信号的缺省行为,这样做是为了防止如果信号处理函数内部也发送了这个信号可能导致的无限循环,然后信号处理函数被调用。(因此如果希望捕捉将来同种类型的信号,从当前这个信号的处理函数返回之前要调用signal函数重新设备信号处理函数)

信号处理函数能够执行的工作类型是很有限的,如果信号是异步的就是不是由于调用abort或raise函数引起的,信号处理函数便不应调用除signal之外的任何函数库,而且,信号处理函数处理能向一个类型为volatile  sig_atomic_t的静态变量赋一个值以外,可能无法访问其他任何静态数据。程序的剩余部分必须定期检查变量的值,看看是否有信号发生。

      这些严格的限制是由于信号处理的本质产生的,信号通常用于提示发生了错误,在这些情况下,CPU的行为是精确定义的,但是程序中的错误所处的上下文环境可能很不相同,因此它们并不一定能够良好定义。例如,当strcpy函数正在执行时产生一个信号,可能目标字符串并不是以NUL字节终结,或者当一个函数被调用时如果产生一个信号,当时堆栈可能处于不完整的状态,这时如果依赖这种上下文环境的库函数被调用,它们就可能失败,并引发另一个信号。访问限制定义了在信号处理函数中保证能够运行的最小功能,类型sig_atomic定义了一种CPU可以以原子方式访问的数据类型,也就是不可分割的访问单位,例如在一个16位机器上可以以原子方式访问一个16位整数,在访问非原子数据的中间步骤时如果产生一个信号可能导致不一致的结果,因此限制在原子单位可以消除这种可能性。

原创粉丝点击