基本概念
信号是软件类型的中断,但不是中断,中断是指由外部设备通过硬件请求的方式产生的中断,信号是是由CPU运行程序错误或执行内部程序调用对于异步事件的响应。
信号与中断的区别
相同点:
(1)采用了相同的异步通信方式;
(2)当检测出有信号或中断请求时,都暂停正在执行的程序而转去执行相应的处理程序;
(3)都在处理完毕后返回到原来的断点;
(4)对信号或中断都可进行屏蔽。
不同点:
(1)中断有优先级,而信号没有优先级,所有的信号都是平等的;
(2)信号处理程序是在用户态下运行的,而中断处理程序是在核心态下运行;
(3)中断响应是及时的,而信号响应通常都有较大的时间延迟。
常用信号
进程对信号的三种处理方式
(1)忽略信号
不采取任何操作、有两个信号不能被忽略:SIGKILL(9号信号)和SIGSTOP。
(2)捕获并处理信号
内核中断正在执行的代码,转去执行先前注册过的处理程序。
(3)执行默认操作
默认操作通常是终止进程,这取决于被发送的信号。
函数signal
#include <signal.h> typedef void (*sighandler_t)(int); sighandler_t signal(int signum,sighandler_t handler);
RETURN VALUE signal() returns the previous value of the signal handler, or SIG_ERR on error. In the event of an error, errno is set to indicate the cause.
signal是一个带signum和handler两个参数的函数,准备捕捉或屏蔽的信号由参数signum给出,接收到指定信号时将要调用的函数由handler给出
handler这个函数必须有一个int类型的参数(即接收到的信号状态码),它本身的类型是void
handler也可以是下面两个特殊值:SIG_IGN (屏蔽该信号) ,SIG_DFL( 恢复默认行为)
#define SIG_ERR (void (*)())-1 #define SIG_DEL (void (*)())0 #define SIG_IGN (void (*)())1
signal信号捕获函数
#include<stdio.h> #include<unistd.h> #include<signal.h> #include<stdlib.h> static void usr(int num) { printf("the signal number is %d\n",num); if(num==SIGINT) { printf("SIGINT signal occured\n"); exit(0); } } int main() { if(signal(SIGINT,usr)==SIG_ERR) { printf("can't catch SIGINT signal\n"); } for(;;) { pause(); } return 0; }
屏蔽信号函数
#include<stdio.h> #include<unistd.h> #include<signal.h> #include<stdlib.h> static void usr(int num) { printf("the signal number is %d\n",num); if(num==SIGINT) { printf("SIGINT signal occured\n"); exit(0); } } int main() { if(signal(SIGINT,SIG_IGN)==SIG_IGN) { signal(SIGINT,usr); } for(;;) { pause(); } return 0; }
signal函数恢复默认行为
#include<stdio.h> #include<unistd.h> #include<signal.h> #include<stdlib.h> void usr(int num) { printf("signal num is %d\n",num); if(num==SIGINT) { printf("SIGINT signal occured!\n"); } } int main() { char ch; if(signal(SIGINT,usr)==SIG_ERR) { printf("error!"); } while((ch=getchar())!='e') { pause(); } signal(SIGINT,SIG_DFL); for(;;) { pause(); } return 0; }