信号的发送

1、可靠信号与不可靠信号

  可靠信号都是实时信号,不可靠信号都是非实时信号。实时信号都支持排队,都是可靠信号。

  

  不可靠信号的早期问题:1、UNIX进程每次处理信号后,将对信号响应设置为默认动作,而LINUX中再次发送不会重置默认动作,继续是handler.
早期解决这个问题的方法是,在信号处理程序最后继续调用signal(SIGINT,handler),重新安装该信号;
void handler(int sig)//sig是signum
{
printf("recv a sig=%d ",sig);
signal(SIGINT,handler);//还是有问题,在安装时来信号了,还是执行默认程序。
}


2、早期UNIX下的不可靠信号主要是进程可能对信号做出错误反应导致信号丢失。处理SIGINT的handler还未返回时,又来了好几个SIGINT,保留一个,后续
就丢弃了。不排队。


3、Linux下调用完信号处理程序不必重新安装信号处理函数。LINUX下的不可靠信号问题主要是第二方面信号可能丢失。

  可靠信号(实时信号):原来定义的信号已有许多应用,不好改动,最终只好新加一些信号并且保证它们一开始就是可靠信号,支持排队不会丢失,主要指
SIGRTMIN--SIGRTMAX33-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 ",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
");
30     }
31     return 0;
32 }
33 void handler(int sig)//sig是signum
34 {
35     printf("recv a sig=%d
",sig);
36     //alarm(1);//每隔一秒发送一次。,间接递归 han-alrm-han
37 }
原文地址:https://www.cnblogs.com/wsw-seu/p/8366457.html