[root@server myprogram]# kill -l
1) SIGHUP 2) SIGINT 3) SIGQUIT 4) SIGILL
5) SIGTRAP 6) SIGABRT 7) SIGBUS 8) SIGFPE
9) SIGKILL 10) SIGUSR1 11) SIGSEGV 12) SIGUSR2
13) SIGPIPE 14) SIGALRM 15) SIGTERM 17) SIGCHLD
18) SIGCONT 19) SIGSTOP 20) SIGTSTP 21) SIGTTIN
22) SIGTTOU 23) SIGURG 24) SIGXCPU 25) SIGXFSZ
26) SIGVTALRM 27) SIGPROF 28) SIGWINCH 29) SIGIO
30) SIGPWR 31) SIGSYS 34) SIGRTMIN 35) SIGRTMIN+1
36) SIGRTMIN+2 37) SIGRTMIN+3 38) SIGRTMIN+4 39) SIGRTMIN+5
40) SIGRTMIN+6 41) SIGRTMIN+7 42) SIGRTMIN+8 43) SIGRTMIN+9
44) SIGRTMIN+10 45) SIGRTMIN+11 46) SIGRTMIN+12 47) SIGRTMIN+13
48) SIGRTMIN+14 49) SIGRTMIN+15 50) SIGRTMAX-14 51) SIGRTMAX-13
52) SIGRTMAX-12 53) SIGRTMAX-11 54) SIGRTMAX-10 55) SIGRTMAX-9
56) SIGRTMAX-8 57) SIGRTMAX-7 58) SIGRTMAX-6 59) SIGRTMAX-5
60) SIGRTMAX-4 61) SIGRTMAX-3 62) SIGRTMAX-2 63) SIGRTMAX-1
64) SIGRTMAX
可见,我这里有64个信号,并且从1开始排序
那么对于信号的处理是怎么一回事情呢?其实,进程中对于信号的处理是异步的,不管进程在干什么,那么是个死循环,也会去响应信号,去做信号处理函数
譬如:
int main()
{
while(1) ;
return 0;
}
[root@server myprogram]# gcc -o test test.c
[root@server myprogram]# ./test
当我们按下Ctrl+c的时候,进程终止,这是进程响应SIGINT信号的结果
为了更明白一点,我们这样做
[root@server myprogram]# gcc -o test test.c
[root@server myprogram]# ./test &
[1] 1790
[root@server myprogram]# kill -SIGSEGV 1790
[root@server myprogram]#
[1]+ Segmentation fault ./test
[root@server myprogram]#
想向进程发送SIGSEGV信号,用kill -SIGSEGV 1790的命令
为什么要enter两次它才输出segmentation fault呢?因为在进程1790结束之前已经已经回到了shell提示符,等待用户输入下一条命令,shell不希望段错误的信息和用户的输入交错在一起,所以等待用户输入命令以后才显示进程发生了段错误,并且生成一个core文件。
下面看一个示例
#include
#include
#include
#include
void sigusr_handler(int signo)//用户信号1和用户信号2的处理函数
{
switch(signo)
{
case SIGUSR1:
printf("Parent : catch SIGUSR1\n");
break;
case SIGUSR2:
printf("Child : catch SIGUSR2\n");
break;
default:
printf("should not be here\n");
break;
}
return ;
}
int main(void)
{
pid_t ppid, cpid;
if(signal(SIGUSR1, sigusr_handler) == SIG_ERR)
{
perror("can't set handler for SIGUSR1");
exit(1);
}
if(signal(SIGUSR2, sigusr_handler) == SIG_ERR)
{
perror("can't set handler for SIGUSR2");
exit(1);
}
ppid = getpid();//后去进程ID
if((cpid = fork()) <0)//fork创建子进程
{
perror("fail to fork");
exit(1);
}
else if(cpid == 0)//在子进程中
{
printf("child\n");
if(kill(ppid, SIGUSR1) == -1)//往父进程发SIGUSR1信号
{
perror("fail to send signal");
exit(1);
}
while(1) ;
}
else//在父进程中
{
//printf("parent\n");
sleep(1);
if(kill(cpid, SIGUSR2) == -1)//往子进程中发SIGUSR2信号
{
perror("fail to send signal");
exit(1);
}
printf("kill child\n");
if(kill(cpid, SIGKILL) == -1)//kill子进程
{
perror("fail to send signal");
exit(1);
}
if(wait(NULL) == -1)//等待一个子进程退出
{
perror("fail to wait");
exit(1);
}
}
return 0;
}
信号是有限的,我们不能随便定义自己的信号,有两个信号是留给用户自己用的,分别是SIGUSR1,SIGUSR2。
这个例子实现了发送信号,信号处理函数的应用
程序执行结果如下:
[root@server myprogram]# gcc -o test test.c
[root@server myprogram]# ./test
child
Parent : catch SIGUSR1
kill child
Child : catch SIGUSR2
有趣的是,如果我只是掉printf("child");这一句,那么Child : catch SIGUSR2这一句也打印不出来,等哪位知道原因的仁兄指教。。。