目录
首先认识几个相关的信号函数,signal、kill、raise、pause。
一、相关函数分析
signal函数
void (*signal(int signum,void(* handler)(int)))(int);
说明:当前进程收到signum对应的信号之后,会执行handler指向的函数。
其中signum有
#define SIGHUP 1 /* Hangup (POSIX). */
#define SIGINT 2 /* Interrupt (ANSI). */
#define SIGQUIT 3 /* Quit (POSIX). */
#define SIGILL 4 /* Illegal instruction (ANSI). */
#define SIGTRAP 5 /* Trace trap (POSIX). */
#define SIGIOT 6 /* IOT trap (4.2 BSD). */
#define SIGABRT SIGIOT /* Abort (ANSI). */
#define SIGEMT 7
#define SIGFPE 8 /* Floating-point exception (ANSI). */
#define SIGKILL 9 /* Kill, unblockable (POSIX). */
#define SIGBUS 10 /* BUS error (4.2 BSD). */
#define SIGSEGV 11 /* Segmentation violation (ANSI). */
#define SIGSYS 12
#define SIGPIPE 13 /* Broken pipe (POSIX). */
#define SIGALRM 14 /* Alarm clock (POSIX). */
#define SIGTERM 15 /* Termination (ANSI). */
#define SIGUSR1 16 /* User-defined signal 1 (POSIX). */
#define SIGUSR2 17 /* User-defined signal 2 (POSIX). */
#define SIGCHLD 18 /* Child status has changed (POSIX). */
#define SIGCLD SIGCHLD /* Same as SIGCHLD (System V). */
#define SIGPWR 19 /* Power failure restart (System V). */
#define SIGWINCH 20 /* Window size change (4.3 BSD, Sun). */
#define SIGURG 21 /* Urgent condition on socket (4.2 BSD). */
#define SIGIO 22 /* I/O now possible (4.2 BSD). */
#define SIGPOLL SIGIO /* Pollable event occurred (System V). */
#define SIGSTOP 23 /* Stop, unblockable (POSIX). */
#define SIGTSTP 24 /* Keyboard stop (POSIX). */
#define SIGCONT 25 /* Continue (POSIX). */
#define SIGTTIN 26 /* Background read from tty (POSIX). */
#define SIGTTOU 27 /* Background write to tty (POSIX). */
#define SIGVTALRM 28 /* Virtual alarm clock (4.2 BSD). */
#define SIGPROF 29 /* Profiling alarm clock (4.2 BSD). */
#define SIGXCPU 30 /* CPU limit exceeded (4.2 BSD). */
#define SIGXFSZ 31 /* File size limit exceeded (4.2 BSD). */
如果handler不是函数指针,则必须是SIG_IGN(忽略当前的信号)、SIG_DFL(将参数指定的信号重新设为系统预设的信号处理方式)。
信号发生之后会跳到指定的handler处理函数,系统这时候相当于把signum对应的默认处理方式替换为用户指定的处理方式,等执行完用户自定的处理方式之后,系统会把它替换回来。如果想替换系统原来的默认处理方式可以参考函数sigaction。
kill函数
int kill(pid_t pid,int signum);
说明:该函数用于向指定的进程pid,发送sig信号编号。
其中参数pid有以下情景:
pid>0 | 指定的进程号 |
pid=0 | 将信号传给与当前进程相同进程组的所有进程 |
pid=-1 | 将信号传递给系统的所有进程 |
pid<-1 | 将信号传递给进程组识别码为PID绝对值的所有进程 |
sig参考上面的signal对应的signum。
raise函数
int raise (int signum);
说明:向同一进程发送sig编号的信号。它与kill的区别是,raise不可以指定pid,只能指向当前的进程。
pause函数
int pause(void);
说明:让当前进程暂停(进入睡眠模式)直到被信号中断。
二、实例展示
实例1,signal&alarm&pause
signal注册一个SIG_ALARM处理函数,pause暂停程序返回,等signal处理完后,继续执行
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
void alarmHandler(){
printf("alarmHandler func.\n");
}
int main(){
int ret;
printf("listen signal...\n");
signal(SIGALRM, &alarmHandler);
ret = alarm(5);
pause();// wait until signal arrived
printf("ok ret is %d\n", ret);
return 0;
}
运行结果:
listen signal...
alarmHandler func.
ok ret is 0
实例2,signal&kill&raise
实例展示kill和raise的使用,通过fork创建一个子进程,父进程用raise发送信号给自己,子进程用kill发送给自己或同组的其它进程,同事我们可以看到子进程继承了父进程的signal函数。
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
#include <sys/types.h>
void my_func(int sig_no){
if(sig_no == SIGINT){
printf("I have get SIGINT pid=%d\n", getpid());
}else if(sig_no == SIGQUIT){
printf("I have get SIGQUIT pid=%d\n", getpid());
}
}
int main(){
pid_t pid, ppid, cpid;
printf("Waitting for SIGINT or SIGQUIT\n");
signal(SIGINT, my_func);
signal(SIGQUIT, my_func);
pid = fork();
if (pid > 0)
{
ppid = getpid();
printf("parent process pid=%d\n", ppid);
raise(SIGQUIT);
}else if (pid == 0)
{
cpid = getpid();
printf("chlid process pid=%d\n", cpid);
sleep(1);
kill(0, SIGINT);
//kill(ppid, SIGINT);
//kill(cpid, SIGINT);
//raise(SIGQUIT);
}
pause();
exit(0);
}
运行结果
Waitting for SIGINT or SIGQUIT
parent process pid=111605
I have get SIGQUIT pid=111605
chlid process pid=111606
I have get SIGINT pid=111606
I have get SIGINT pid=111605