• 信号的发送


    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 }
  • 相关阅读:
    复制过来的东西也不靠谱,微信公众号第三方平台的API
    微信的加解密
    郁闷的错误
    Jquery Table 操作
    Html获取经纬度
    Mvc5 Html.EditorFor
    MVC5 烂笔头
    第三方应用开发的一点心得
    Socket 简易静态服务器 WPF MVVM模式(三)
    Socket 简易静态服务器 WPF MVVM模式(二)
  • 原文地址:https://www.cnblogs.com/wsw-seu/p/8366457.html
Copyright © 2020-2023  润新知