zoukankan      html  css  js  c++  java
  • Linux进程间通信-信号

    1.什么是信号
    信号是Linux系统响应某些条件而产生的一个事件,接收到该信号的进程会执行相应的操作。

    2.信号的产生
    1)由硬件产生,如从键盘输入Ctrl+C可以终止当前进程
    2)由其他进程发送,如可在shell进程下,使用命令 kill -信号标号 PID,向指定进程发送信号。
    3)异常,进程异常时会发送信号

    3.信号的处理
    信号是由操作系统来处理的,说明信号的处理在内核态。
    信号不一定会立即被处理,此时会储存在信号的信号表中。
    处理过程示意图:

    由上图中可看出信号有三种处理方式:
    1)忽略
    2)默认处理方式:操作系统设定的默认处理方式
    3)自定义信号处理方式:可自定义信号处理函数

    4.自定义信号处理方式
    1)signal函数
    原型:
    void (*signal(int sig, void (*func)(int)))(int);
    sig:信号值
    func:信号处理函数指针,参数为信号值
    代码示例如下:

    #include <signal.h>
    #include <stdio.h>
    void ouch(int sig)
    {
        printf("
    OUCH! - I got signal %d
    ", sig);
        //恢复终端中断信号SIGINT的默认行为
        (void) signal(SIGINT, SIG_DFL);
    }
    int main()
    {
        //改变终端中断信号SIGINT的默认行为,使之执行ouch函数
        //而不是终止程序的执行
        (void) signal(SIGINT, ouch);
        while(1)
        {
            printf("Hello World!
    ");
            sleep(1);
        }
        return 0;
    }

    输出结果:

    2)sigaction函数
    原型:
    int sigaction(int sig,const struct sigaction *act,struct sigaction *oact);
    sig:信号值
    act:指定信号的动作
    oact:保存原信号的动作

    sigaction结构体的定义如下:
    void (*)(int) sa_handler;处理函数指针,相当于signal函数的func参数。
    sigset_t sa_mask;处理过程中,屏蔽对sa_mask信号集的处理,sa_mask可以消除信号间的竞态。
    int sa_flags;信号处理修改器:处理函数执行完后,信号处理方式修改。如SA_RESETHAND,将信号处理方式重置为SIG_DFL
    代码示例如下:

    #include <stdio.h>
    #include <signal.h>
    void ouch(int sig)
    {
        printf("
    OUCH! - I got signal %d
    ", sig);
    }
    int main()
    {
        struct sigaction act;
        act.sa_handler = ouch;
        //创建空的信号屏蔽字,即不屏蔽任何信息
        sigemptyset(&act.sa_mask);
        //使sigaction函数重置为默认行为
        act.sa_flags = SA_RESETHAND;
        sigaction(SIGINT, &act, 0);
        while(1)
        {
            printf("Hello World!
    ");
            sleep(1);
        }
        return 0;
    }

    输出结果:

    4.信号的发送
    1)kill函数
    int kill(pid_t pid,int signo);
    pid:进程ID
    signo:信号值

    2)raise函数:只能向当前进程发信号
    int raise(int signo);
    signo:信号值

    3)abort函数:发送SIGABRT信号,可以让进程异常终止
    void abort(void);

    4)alarm函数:发送SIGALRM闹钟信号
    unsigned int alarm(unsigned int seconds);

    5.信号的阻塞
    阻塞是阻止进程收到该信号,此时信号处于未决状态,放入进程的未决信号表中,
    当解除对该信号的阻塞时,未决信号会被进程接收。

    1)阻塞信号
    原型:
    int sigprocmask(int how,const sigset_t *set,sigset_t *oset);
    how:设置block阻塞表的方式
    a.SIG_BLOCK:将信号集添加到block表中
    b.SIG_UNBLOCK:将信号集从block表中删除
    c.SIG_SETMASK:将信号集设置为block表
    set:要设置的集合
    oset:设置前保存之前block表信息

    2)获取未决信号
    前面已经讲过,阻塞的信号处于未决的状态,会放入进程的未决信号表。
    原型:
    int sigpending(sigset_t *set);
    set:out型参数,会将获得的当前进程的pending未决表中的信号集传入。

    代码示例如下:

    #include <stdio.h>
    #include <sys/signal.h>
    #include <sys/types.h>
    #include <signal.h>
    void func(int num)
    {
      printf("catch signal number is %d",num);
    }
    void printfpendingsignal(sigset_t *set)
    {
      int i;
      for(i=1;i<32;++i)
      {
        if(sigismember(set,i))
        {
          printf("1");
        }
        else
        {
          printf("0");
        }
      }
      printf("
    ");
    }
    int main()
    { 
      sigset_t s,p,o;
      signal(SIGINT,func);
      sigemptyset(&s);
      sigemptyset(&p);
      sigemptyset(&o);
      sigaddset(&s,SIGINT);
      sigprocmask(SIG_SETMASK,&s,&o);
      int count=0;
      while(1)
      {
        sigpending(&p);
        printfpendingsignal(&p);
        sleep(1);
        if(count++==10)
        {
          printf("recover!
    ");
          sigprocmask(SIG_SETMASK,&o,NULL);
        }
      }
      return 0;
    }

    输出结果:

    6.信号处理函数的安全问题
    如果信号处理过程中被中断,再次调用,然后返回到第一次调用时,要保证操作的正确性。
    这就要求信号处理函数必须是可重入的。
    可重入函数表如下:

    7.一些常见的信号

    如果进程接收到上面的这些信号,又没有安排捕获它,进程就会终止。

    其他的一些信号如下:

  • 相关阅读:
    Elasticsearch学习系列之介绍安装
    Python学习系列之文件操作
    Python学习系列之异常处理
    Python学习系列之装饰器
    windows 修改xhsell安全加密配置
    ipv6nginx错误
    zabbix 硬盘状态收集,制作表格
    申请免费ssl证书
    gitlab 搭建与迁移
    mogilefsdBUG mogilefsd[15624]: crash log: Modification of a read-only value attempted at /usr/local/share/perl5/Sys/Syscall.pm line 227
  • 原文地址:https://www.cnblogs.com/shijingjing07/p/5672784.html
Copyright © 2011-2022 走看看