linux信号
Linux环境下,一般使用signal函数或者sigaction绑定对特定信号的处理。
signal函数
原型如下:
#include <signal.h> typedef void (*sighandler_t)(int); sighandler_t signal(int signum, sighandler_t handler);
signal函数的而作用就是将信号与回调函数绑定在一起。
第一个参数就是信号类型,例如SIGINT(2)等,详细的定义见signal.h头文件中。
第二个参数是函数指针,该函数为一个形参为int,返回值为void的函数,可以将其理解为信号产生医护的回调函数。
返回值:成功返回信号处理程序之前的值,当发生错误时返回 SIG_ERR,并且errno也会被设置。
测试代码:
#include <signal.h> #include <stdio.h> #include <stdlib.h> #include <unistd.h> static void sig_int(int signo) { printf("interrupt!\n"); } int main(int argc, char **argv) { if (signal(SIGINT, sig_int) == SIG_ERR) { printf("error 1\n"); exit(1); } pause(); return 0; }
程序运行以后暂停,当用户按下CTRL+C以后,会打印“Interrupt!”然后退出。
其实,sig_int函数可以根据传递的参数,决定对应的动作,我们可以把该函数绑定多个不同的信号,例如:
#include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <signal.h> #include <stdio.h> #include <stdlib.h> #include <unistd.h> static void sig_handler(int signo) { switch (signo) { case SIGINT: printf("SIGINT!\n"); break; case SIGTSTP: printf("SIGTSTP!\n"); break; case SIGALRM: printf("SIGALRM!\n"); break; } } int main(int argc, char **argv) { if (signal(SIGINT, sig_handler) == SIG_ERR) { exit(1); } if (signal(SIGTSTP, sig_handler) == SIG_ERR) { exit(1); } if (signal(SIGALRM, sig_handler) == SIG_ERR) { exit(1); } while (1) { alarm(1); pause(); } return 0; }
使用Ctrl+Z,Ctrl+C可以测试SIGTSTP、SIGINT,AIGALAM是定时产生的,需要退出程序时,使用CTRL+\。
这里再把pause函数说一下:
pause() returns only if a signal is received, in which case the signal is handled, and pause() returns -1 and sets errno to EINTR. If the kernel raises an ignored signal, the process does not wake up.
调用该函数以后,只有信号产生的时候才会返回。
sigaction函数
函数原型:
#include <signal.h> int sigaction(int signum, const struct sigaction *act,struct sigaction *oldact);
第一个参数同样是信号类型;
第二个和第三个参数是同一类型的结构体,该结构体和函数同名,用来表示对信号类型采取的行为,前一个指向了将被设置的处理方式,后二个用于 保存先前的处理方式 。
其定义如下:
struct sigaction { void (*sa_handler)(int); void (*sa_sigaction)(int, siginfo_t *, void *); sigset_t sa_mask; int sa_flags; void (*sa_restorer)(void); };
第一个参数sa_handler 和signal中的第二个参数一样,是signum对应的处理函数。
第二个参数sa_sigaction也是signum的处理函数。
第三个参数是指明哪些信号要被屏蔽;
第四个参数决定了在signum产生时,到底是使用sa_handler 还是sa_sigaction作为处理函数;
最后一个参数不使用(The sa_restorer field is not intended for application use. )
测试代码:
#include <signal.h> #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <string.h> struct sigaction sa; static void sig_alm(int signo) { printf("sig_alm:sig=%d\n",signo); sa.sa_flags = SA_SIGINFO; } void sig_alt(int sig, siginfo_t *info, void *ucontext) { printf("sig_alt:sig=%d\n",sig); sa.sa_flags = 0; } int main(int argc, char **argv) { memset(&sa, 0, sizeof(sa)); sa.sa_handler = &sig_alm; sa.sa_sigaction = &sig_alt; //sa.sa_flags = SA_SIGINFO; sigaction(SIGALRM, &sa, NULL); while(1) { alarm(1); pause(); } return 0; }