signal函数

在<signal.h>这个头文件中
signal(参数1,参数2);
参数1:我们要进行处理的信号,系统的信号我们可以再终端键入kill -l查看(共64个)。其实这些信号是系统定义的宏。
参数2:我们处理的方式(是系统默认还是忽略还是捕获)。
这三种方式分别为:SIG_IGN忽略、SIG_DFL默认方式、void(*handler)(int)捕获方式
eg1:

(1)eg: signal(SIGINT ,SIG_ING );

//SIG_ING 代表忽略SIGINT信号,SIGINT信号代表由InterruptKey产生,通常是CTRL +C 或者是DELETE 。发送给所有ForeGround Group的进程。

#include<stdio.h>
#include<signal.h>
int main(int argc,char** argv)
{
    signal(SIGINT,SIG_IGN);
    for( ; ; );
    return 0;
}
这时,我们按下ctrl+c没有反应。
如果我们想结束程序可以按ctrl+\组合键结束进程。
其实当我们按下ctrl+\组合键时,就产生了SIGOUIT信号。
eg2:
//SIGINT信号代表由InterruptKey产生,通常是CTRL +C或者是DELETE。发送给所有ForeGroundGroup的进程。 SIG_DFL代表执行系统默认操作,其实对于大多数信号的系统默认动作时终止该进程。这与不写此处理函数是一样的。
#include<stdio.h>
#include<signal.h>
int main(int argc,char** argv)
{
    signal(SIGINT,SIG_DFL);
    while(1);
    return 0;
}
这时候按下ctrl+c来终止该进程,把signal(SIGINT,SIG_DFL)这句去掉是一样的。
此处原因是,恢复ctrl+c的默认功能。
eg3:
void (*signal(int sig,void(* handler)(int)))(int);
int (*p)();
这是一个函数指针,p指向的函数是一个不带任何参数,并且返回值为int的一个函数
int (*fun())();
这个式子与上面式子的区别在于用fun()代替了p,而fun()是一个函数,所以说就可以看成是fun()这个函数执行之后,它的返回值是一个函数指针,这个函数指针(其实就是上面的p)所指向的函数是一个不带任何参数,并且返回值为int的一个函数。
void(*signal(int signo,void(*handler)(int)))(int);就可以看成是signal()函数(它自己带两个参数,一个为整型,一个为函数指针的函数),而这个signal()函数的返回值也为一个函数指针,这个函数指针指向一个带一个整型参数,并且返回值为void的一个函数。
在写信号处理函数时对于信号处理的函数也是void sig_fun(int signo);这种类型,恰好与上面signal()函数所返回的函数指针所指向的函数是一样的,void(signal())(int);
signal是一个函数,他返回一个函数指针,后者所指向的函数接收一个整型参数,且没有返回值,仔细看,是不是函数,指向信号处理函数,就可以执行函数了(signal内部时,signal把信号作为参数传递给handler信号处理函数,接着signal函数返回指针,并且又指向信号处理函数,就开始执行它)。
那么,signal函数的参数又是如何呢?signal函数接受两个参数:一个整型的信号编号,以及一个指向用户定义的信号处理函数的指针。我们此前已经定义了指向用户定义的信号处理函数的指针sfp:
void(*sfp)(int);
sfp的类型可以通过将上面的声明中的sfp去掉而得到,即void(*)(int).此外,signal函数的返回值是一个指向调用前的用户定义信号处理函数的指针,这个指针的类型与sfp指针类型一致。因此,我们可以如下声明
signal函数:
void (*signal(int,void(*)(int)))(int);
同样地,使用typedef 可以简化上面的函数声明:
typedef void(*HANDLER)(int);
HANDLED signal(int,HANDLER);
eg:
#include<stdio.h>
#include<signal.h>
typedef void(* signal_handler)(int);
void signal_handler_fun(int signal_num)
{
    printf("catch  signal  %d\n",signal_num);
}
int main(int argc,char* argv[])
{
    signal_handler p_signal = signal_handler_fun;
    signal(SIGINT,p_signal);
    while(1);
    return 0;
}
其实在这里可以直接调用函数的,倒是多此一举了。
更改如下:
#include<stdio.h>
#include<signal.h>
void signal(int signo)
{
    printf("catch signal\n");
}
int main(int argc,char** argv)
{
    signal(SIGINT,signal);
    while(1);
    return 0;
}
常用的signal如下:
Signal Description
SIGABRT 由调用abort函数产生,进程非正常退出
SIGALRM 用alarm函数设置的timer超时或setitimer函数设置的interval timer超时
SIGBUS 某种特定的硬件异常,通常由内存访问引起
SIGCANCEL 由Solaris Thread Library内部使用,通常不会使用
SIGCHLD 进程Terminate或Stop的时候,SIGCHLD会发送给它的父进程。缺省情况下该Signal会被忽略
SIGCONT 当被stop的进程恢复运行的时候,自动发送
SIGEMT 和实现相关的硬件异常
SIGFPE 数学相关的异常,如被0除,浮点溢出,等等
SIGFREEZE Solaris专用,Hiberate或者Suspended时候发送
SIGHUP 发送给具有Terminal的Controlling Process,当terminal被disconnect时候发送
SIGILL 非法指令异常
SIGINFO BSD signal。由Status Key产生,通常是CTRL+T。发送给所有Foreground Group的进程
SIGINT 由Interrupt Key产生,通常是CTRL+C或者DELETE。发送给所有ForeGround Group的进程
SIGIO 异步IO事件
SIGIOT 实现相关的硬件异常,一般对应SIGABRT
SIGKILL 无法处理和忽略。中止某个进程
SIGLWP 由Solaris Thread Libray内部使用
SIGPIPE 在reader中止之后写Pipe的时候发送
SIGPOLL 当某个事件发送给Pollable Device的时候发送
SIGPROF Setitimer指定的Profiling Interval Timer所产生
SIGPWR 和系统相关。和UPS相关。
SIGQUIT 输入Quit Key的时候(CTRL+\)发送给所有Foreground Group的进程
SIGSEGV 非法内存访问
SIGSTKFLT Linux专用,数学协处理器的栈异常
SIGSTOP 中止进程。无法处理和忽略。
SIGSYS 非法系统调用
SIGTERM 请求中止进程,kill命令缺省发送
SIGTHAW Solaris专用,从Suspend恢复时候发送
SIGTRAP 实现相关的硬件异常。一般是调试异常
SIGTSTP Suspend Key,一般是Ctrl+Z。发送给所有Foreground Group的进程
SIGTTIN 当Background Group的进程尝试读取Terminal的时候发送
SIGTTOU 当Background Group的进程尝试写Terminal的时候发送
SIGURG 当out-of-band data接收的时候可能发送
SIGUSR1 用户自定义signal 1
SIGUSR2 用户自定义signal 2
SIGVTALRM setitimer函数设置的Virtual Interval Timer超时的时候
SIGWAITING Solaris Thread Library内部实现专用
SIGWINCH 当Terminal的窗口大小改变的时候,发送给Foreground Group的所有进程
SIGXCPU 当CPU时间限制超时的时候
SIGXFSZ 进程超过文件大小限制
SIGXRES Solaris专用,进程超过资源限制的时候发送
posted @ 2016-08-21 12:29  dmfsimle  阅读(117)  评论(0)    收藏  举报