Linux里信号是系统响应了某些条件而生成的一个事件,捕获到该信号的进程会相应地采取一些行动;信号是由于某些错误条件造成的,比如内存段冲突,浮点处理器错误或者非法指令等;它们由shell和终端处理器生成来引起中断,还可以作为在进程间传递消息或者修改行为的一种方式,明确地由一个进程发送给另一个进程
所有信号都在头文件signal.h里定义,以SIG开头,有兴趣可以自行搜索
如果进程接收到一个信号,但是事先并没有安排来捕获它,进程就会立即终止,通常系统会生成核心转储文件core,并存在当前目录下;这个文件是进程在内存中的映像,大家都都知道的,可以用来调试定位
通常Ctrl+C就会向前台进程也就是当前运行的程序发送SIGINT信号,这将引起该程序的终止,除非它事先安排了捕获这个信号
signal库函数可以用来处理信号,定义如下:
#include <signal.h> void (*signal(int sig, void(*func)(int)))(int);
看到这函数我也是醉了,signal带了sig和func两个参数,准备捕获或者忽略的信号又参数sig给出,接收到指定的信号后将要调用的函数由参数func给出,信号处理函数必须有一个int类型的参数,也就是向信号处理程序传送一个整形参数,也就是接收到的信号代码,并返回void
下面的程序响应用户输入的Ctrl+C,第一次会打印一条信息并没有终止程序的运行,而第二次Ctrl+C的时候,程序结束运行:
lihui@2015 ~ $ cat he.c #include <stdio.h> #include <signal.h> #include <unistd.h> void ouch(int sig){ printf("OUCH! - I got signal %d\n", sig); (void)signal(SIGINT, SIG_DFL); } int main(){ (void)signal(SIGINT, ouch); while(1){ printf("Hello World!\n"); sleep(1); } return 0; } lihui@2015 ~ $ ./a.exe Hello World! Hello World! Hello World! ^C OUCH! - I got signal 2 Hello World! Hello World! Hello World! Hello World! Hello World! ^C lihui@2015 ~ $
第一次Ctrl+C会让程序做出响应,然后程序继续运行,再次Ctrl+C,程序就会结束运行,因为SIGINT信号的处理方式已经恢复为默认行为,终止程序运行
这里的SIG_DFL含义是恢复默认行为,也就是ouch来处理了按下Ctrl+C所产生的SIGINT信号,程序会在ouch函数处理完毕之后继续执行,但是信号处理方式已经恢复到默认行为,当接收到第二个SIGINT信号后,会采取默认的行动,终止程序的运行
这里信号处理函数signal使用了一个整型参数SIGINT(终端中断),它就是引起该函数被调用的信号代码,如果需要在一个函数里处理多个信号,这个参数就很有用了,可以使用不同信号的名字来处理,当然这里打印出来了SIGINT的值为2
试想,如果把ouch里的signal去掉会怎么样,谁有兴趣可以试试~!