在Linux中,要发送一个信号相当容易。程序员需要知道两个信息:要发送哪个信号,将这个信号发送给哪个进程。可以用 man 7 signal 找到一个可以利用的信号的列表。用户可以只将信号发送给用户自己的进程,也可以以root身份运行从而将信号发送给任意一进程。


Source:


Result:

[work@db-testing-com06-vm3.db01.baidu.com c++]$ ./signal_test

程序已经开始运行,5秒钟后将接收到时钟信号。

距离SIGALRM信号到来还有5秒。

系统接收到了SIGIO信号。

距离SIGALRM信号到来还有4秒。

距离SIGALRM信号到来还有3秒。

距离SIGALRM信号到来还有2秒。

系统接收到了用户自定义信号SIGUSR1。

距离SIGALRM信号到来还有1秒。

5秒钟时间已到,系统接收到了SIGALRM信号!

子进程还剩2秒退出,届时会产生SIGCHLD信号。

子进程还剩1秒退出,届时会产生SIGCHLD信号。

收到SIGCHLD信号,表明我的子进程已经中止,SIGCHLD信号的数值是:17。

------此时程序会停下来等待,请按下ctrl+c送出SIGINT信号-------

已经接收到了SIGINT信号,程序将退出!


信号参考对照表:



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


专用,进程超过资源限制的时候发送

==========================================================================


signal学习推荐:



信号(signal)介绍(Linux中国)


http://www.linux-cn.com/html/linux/system/20070505/27605.shtml

Linux 信号signal处理函数(CSDN)


http://blog.csdn.net/Sunboy_2050/archive/2010/10/16/5945535.aspx

Linux 信号signal处理机制(CSDN)


http://blog.csdn.net/Sunboy_2050/archive/2010/10/16/5945380.aspx

==========================================================================

程序员可以调用 int raise(int signo) 将一个信号发送给它自己。这个函数只带有一个参数,既要发送信号的编号。如:raise(SIGINT); raise(SIGKILL);

让人感兴趣的是函数 unsigned int alarm(unsigned int seconds) 它可以让用户进程在将来某个指定的时间接收到一个信号。alarm()的唯一参数是将来信号SIGALRM应该在多少秒以后发送给用户进程。当用户调用alarm()时,前面任何一个请求的报警信号(不包括悬挂起来被阻塞的SIGALRM信号)都将被取消,调用的返回值是前面请求的剩余时间。alarm()范例如下:

if(signal(SIGALRM,alarmhandler)==SIG_ERR)

{

printf("Couldn't register signal handler./n");

}

alarm(5);      // 5秒钟以后,程序将会收到一个SIGALRM信号

for(i=0;i<10;i++)

{

sleep(3);

}

void alarmhandler(int signum)

{

printf("alarmhandler./n");

}

也可以使用 int setitimer(int which, const struct itimerval *value, struct itimerval *ovalue) 来实现更精确更方便的定时控制。

参数which一般取ITIMER_REAL,它使得用户的计时器根据系统时钟来计算时间。当计数时间到期时,它将发送一个SIGALRM信号。其功能和alarm()一样,所以用户不能将两者同时使用。

结构itimerval的定义如下:

struct itimerval

{

struct timeval it_interval; // 每一次触发报警后应该被复位的值,为0报警被禁止

struct timeval it_value;     // 下一次触发报警的时间,为0报警将只触发一次

};

结构timeval的定义如下:

strut timeval

{

long tv_sec;       // 秒数

long tv_usec;     // 微秒数

};

setitimer()范例如下:

struct itimerval itimer;

itimer.it_interval.tv_usec = 0;     // it_interval字段指定了每一次触发后应该被复位的值

itimer.it_interval.tv_sec     = 2;

itimer.it_value.tv_usec = 0;        // it_value字段指定了直到下一次触发的时间

itimer.it_value.tv_sec     = 5;

setitimer(ITIMER_REAL,&itimer,NULL);

for(i=0;i<10;i++)

{

sleep(3);

}

void alarmhandler(int signum)

{

printf("alarmhandler./n");

}