服务器端程序通常需要处理信号,关于信号的概念不多说,linux操作系统默认有64个信号,用kill -l可列出所有信号,信号是个异步机制的东西,我们这里的信号指的是操作系统给进程或者其他进程给本进程发送的信号,每个信号都由一个信号码及信号处理程序,当进程收到某个信号时,该信号对应的处理程序会被执行,进程创建时指定默认信号处理程序,我们也可以自定义,信号处理程序的调用是 异步的,这就意味着程序的任何位置可能收到信号,这时会调用信号处理程序,当进程收到信号时,操作系统停止执行当前进程,并强制去执行信号处理程序,当信号处理程序执行后,程序返回到中断处继续执行。


如果对嵌入式系统了解,我们应该都知道中断(interrupt),信号与嵌入式系统中的中断类似,不同点在于中断是硬件给操作系统的通知,而信号是操作系统给进程,或其他进程给本进程发的通知。




可以通过按键(ctl + c ,z),命令行(kill ),系统调用(kill)三种方式给进程发送信号.




捕获信号----信号处理程序




大部分信号进程是可以捕获的,也就是说进程可以指定信号处理程序,但有些信号进程是不能捕获的,KILL就是其中之一,


在可捕获的信号中 最著名的应该是大名鼎鼎 SIGSEGV 拉,他的信号码是11,我想每个在linux下面作c c++开发的码农们对他应该是恨之入骨哇。


我们的程序中通常需要自定义处理程序的信号无非那几个,


SIGCHLD:当派生子进程时,必须捕获信号SGICHLD,否则可能产生僵尸进程,SGICHLD的信号处理程序必须正确编写,用waitpid而不用wait避免留下僵尸进程.




SIGPIPE:broken pipe , 写至无读进程的管道, 或者Socket通信SOCT_STREAM的读进程已经终止,而再写入。,此信号的缺省行为就是终止进程,所以如果你还想作其他处理的话一定要捕获之,我所知道的几乎所有网络服务器都有对此信号的处理。


SIGALRM:(超时) alarm函数使用该信号,时钟定时器超时响应


SIGXFSZ:SIGXFSZ 终止进程 文件长度过长,在服务器log模块常用。作log rotate. 


SIGTERM (软中断) 使用不带参数的kill命令时终止进程


SIGHUP (挂起) 当运行进程的用户注销时通知该进程,使进程终止


SIGINT (中断) 当用户按下时,通知前台进程组终止进程


SIGQUIT (退出) 用户按下或时通知进程,使进程终止


SIGILL (非法指令) 执行了非法指令,如可执行文件本身出现错误、试图执行数据段、堆栈溢出




信号编程:




通过系统调用signal执行信号对应的回调,signal参数为信号及信号回调。


linux预先定义了 两个信号 默认处理程序,SIG_IGN及SIG_DEL


SIG_IGN 为进程忽略此信号,如


signal(SIGINT, SIG_IGN);//忽略中断


SIG_DFL:让操作系统给信号指定默认处理程序。




单纯使用signal指定信号在发生信号回调堆叠(执行信号处理程序时又接到信号)会有问题,所以建议使用sigaction/sigprocmask()代替signal,这两种方法提供了阻塞信号处理机制。




信号编程总结:


1. make it short and fast enough: 信号处理程序应该尽量简短并尽快返回,通常做法是在信号处理程序中标记某个变量,然后由主程序间隔去检测变量值做操作,比如nginx, lighttpd的主循环 判断条件是 srv_shutdown,此变量在中断时被职位。


2.尽量用sigaction而不用signal:由于历史原因,signal 信号在堆叠时存在危险,所以尽量用同样简洁而不简单的sigaction :)


3.小心处理哪些 fault 信号:如果你捕获了程序中存在的bug导致的信号( SIGSEV,SIGFPE),不要仍然继续你的程序,除非你知道在干什么,否则你应该清理资源,或产生必要的core dump,因为你不这么做程序迟早还会crash :)


4. 信号不是事件驱动框架:虽然使用信号可以方便实现类似事件驱动程序,但是信号不是做这个的。


​http://users.evtek.fi/~tk/rtp/signals-programming.html​

​http://www.yolinux.com/TUTORIALS/C++Signals.html​