信号的发送
1、可靠信号与不可靠信号
可靠信号都是实时信号,不可靠信号都是非实时信号。实时信号都支持排队,都是可靠信号。
不可靠信号的早期问题:1、UNIX进程每次处理信号后,将对信号响应设置为默认动作,而LINUX中再次发送不会重置默认动作,继续是handler.
早期解决这个问题的方法是,在信号处理程序最后继续调用signal(SIGINT,handler),重新安装该信号;
void handler(int sig)//sig是signum
{
printf("recv a sig=%d\n",sig);
signal(SIGINT,handler);//还是有问题,在安装时来信号了,还是执行默认程序。
}
2、早期UNIX下的不可靠信号主要是进程可能对信号做出错误反应导致信号丢失。处理SIGINT的handler还未返回时,又来了好几个SIGINT,保留一个,后续
就丢弃了。不排队。
3、Linux下调用完信号处理程序不必重新安装信号处理函数。LINUX下的不可靠信号问题主要是第二方面信号可能丢失。
可靠信号(实时信号):原来定义的信号已有许多应用,不好改动,最终只好新加一些信号并且保证它们一开始就是可靠信号,支持排队不会丢失,主要指
从SIGRTMIN--SIGRTMAX(33-64)之间的信号。
同时信号发送函数:sigqueue()支持排队。信号安装函数:sigaction()
非实时不支持排队,前面的30几个信号,不支持排队,SIGHUP--SIGSYS,而且都是不可靠信号;
4、信号发送:
kill -9 pid //向pid 发送9号信号(SIGKILL)
int kill(pid_t pid,int sig)//
参数:
pid>0 sig信号发送给pid进程;
pid==0,sig信号将发送给调用者所在组中的每一个进程;
pid==-1,信号sig将被发送给调用者进程有权限发送的每一个进程(1号进程与自身除外);
pid<-1,信号将发给进程组=-pid中的每一个进程.
1 #include<unistd.h> 2 #include<sys/types.h> 3 #include<sys/stat.h> 4 #include<fcntl.h> 5 #include<stdlib.h> 6 #include<stdio.h> 7 #include<errno.h> 8 #include<string.h> 9 10 #include<signal.h> 11 #define ERR_EXIT(m)\ 12 do\ 13 {\ 14 perror(m);\ 15 exit(EXIT_FAILURE);\ 16 }while(0) //宏要求一条语句 17 void handler(int sig); 18 int main(int argc,char*argv[]) 19 { 20 21 if((signal(SIGUSR1,handler))==SIG_ERR) 22 ERR_EXIT("signal error");//fork之前安装 23 pid_t pid=fork();//子进程继承了信号安装,在向进程组发送信号时,子进程也会调用handler信号处理程序进行处理 24 if(pid==-1) ERR_EXIT("fork error"); 25 if(pid==0){//子进程
//kill(getppid(),SIGUSR1);//向父进程发送信号
26 /*pid=getpgrp();//获取进程组ID 27 kill(-pid,SIGUSR1);//pid<-1,将向pid进程组中每个进程发送sig*/ 28 killpg(getpgrp(),SIGUSR1);//向进程组发送信号 29 exit(EXIT_SUCCESS);//子进程退出 30 } 31 //sleep(5);//父进程并未睡眠5秒,直接返回。因为sleep()函数会被被信号打断。如果想sleep(5),可以如下操作: 32 int n=5; 33 do{ 34 n=sleep(n); //被信号打断返回剩余的睡眠时间 35 }while(n>0); 36 return 0; 37 } 38 void handler(int sig)//sig是signum 39 { 40 printf("recv a sig=%d\n",sig); 41 }
下面是一些信号处理的一些函数:
int rasie(int sig)向调用者自身发送信号,等价于kill(getpid(),sig)
killpg(pgrp,sig) 向进程组发送信号,等价于kill(-pgrp,sig)
sigqueue 给进程发送信号,支持排队
pause() 函数将进程置为可中断睡眠状态,让出CPU时间片。然后它调用schedule()使得LINUX进程调度器找到另一个进程来运行。pause()使调用
者挂起,直到一个信号被捕获时返回。
更多信号发送函数:alarm函数,setitimer函数,abort函数
alarm只能发送 SIGALRM信号(用于时钟信号)
或者手工发送SIGALRM信号: kill -SIGALRM `ps aux | grep 01alarm | grep -v vim | grep -v grep | awk '{print $2}' `
unsigned int alarm(unsigned int seconds) 过了seconds后会产生SIGALRM信号
1 #include<unistd.h> 2 #include<sys/types.h> 3 #include<sys/stat.h> 4 #include<fcntl.h> 5 #include<stdlib.h> 6 #include<stdio.h> 7 #include<errno.h> 8 #include<string.h> 9 10 #include<signal.h> 11 #define ERR_EXIT(m)\ 12 do\ 13 {\ 14 perror(m);\ 15 exit(EXIT_FAILURE);\ 16 }while(0) //宏要求一条语句 17 void handler(int sig); 18 int main(int argc,char*argv[]) 19 { 20 21 22 if(signal(SIGALRM,handler)==SIG_ERR) 23 ERR_EXIT("signal error"); 24 alarm(1);//过一秒发送一个SIGALRM信号 25 for(;;) 26 { 27 28 pause();//被信号唤醒 29 printf("pause return\n"); 30 } 31 return 0; 32 } 33 void handler(int sig)//sig是signum 34 { 35 printf("recv a sig=%d\n",sig); 36 //alarm(1);//每隔一秒发送一次。,间接递归 han-alrm-han 37 }