zoukankan      html  css  js  c++  java
  • 信号

    man 7 signal

     (默认处理动作)

     

    杀死父进程:

     

    由父进程杀死3号子进程:

    raise 函数,给本进程传递信号

    abort 函数

     setitimer 函数

     

     (实现alarm)

    (第一次5s发SIGALRM,之后每隔3s发一次。signal()函数用于捕捉信号)

    实现alarm

    信号集处理函数:

     

     

     

     

    信号捕捉特性

    1. 进程正常运行时,默认PCB中有一个信号屏蔽字,假定为☆,它决定了进程自动屏蔽哪些信号。当注册了某个信号捕捉函数,捕捉到该信号以后,要调用该函数。而该函数有可能执行很长时间,在这期间所屏蔽的信号不由☆来指定。而是用sa_mask来指定。调用完信号处理函数,再恢复为☆。
    2. XXX信号捕捉函数执行期间,XXX信号自动被屏蔽。
    3. 阻塞的常规信号不支持排队,产生多次只记录一次。(后32个实时信号支持排队)

     

     

     

    (在捕捉函数执行期间,屏蔽SIGINT [ctrl+c] 和 SIGQUIT [ctrl+])

    利用SIGCHLD信号捕捉回收子进程:

     

    如果在sigaction注册之前子进程都已结束,则catch不到SIGCHLD.可以先把SIGCHLD block掉,sigaction注册后恢复。

    #include <stdio.h>
    #include <unistd.h>
    #include <sys/wait.h>
    #include <signal.h>
    
    void catch_sig(int num){
        pid_t wpid;
        while((wpid=waitpid(-1,NULL,WNOHANG))>0){
            printf("wait child %d ok
    ", wpid);
        }
    }
    
    int main()
    {
        int i=0;
        sigset_t myset,oldset;
        sigemptyset(&myset);
        sigaddset(&myset,SIGCHLD);
        sigprocmask(SIG_BLOCK,&myset,&oldset);
    
        pid_t pid;
        for(i=0;i<10;i++){
            pid=fork();
            if(pid==0){
                break;
            }
        }
        if(i==10){
            sleep(5);
            struct sigaction act;
            act.sa_flags=0;
            sigemptyset(&act.sa_mask);
            act.sa_handler=catch_sig;
            sigaction(SIGCHLD,&act,NULL);
            sigprocmask(SIG_SETMASK,&oldset,NULL);
            while(1){
                sleep(1);
            }
        }else {
            printf("I am the %d child, pid=%d
    ", i, getpid());
            //sleep(i);
        }
        return 0;
    }

    利用信号实现父子进程相互报数:

    #include <stdio.h>
    #include <unistd.h>
    #include <signal.h>
    
    int flag=0;
    int count;
    
    void cat_son(int num){
       sleep(1); printf(
    "%d ", count); count+=2; flag=1; } void cat_father(int num){
      sleep(1); printf(
    "%d ", count); count+=2; flag=1; } int main() { pid_t pid=fork(); if(pid==0){ count=1; pid_t ppid=getppid(); signal(SIGUSR1,cat_son); while(1){ if(flag==1){ kill(ppid,SIGUSR2); flag=0; } } }else{ sleep(1); count=2; signal(SIGUSR2,cat_father); kill(pid,SIGUSR1); while(1){ if(flag==1){ kill(pid,SIGUSR1); flag=0; } } } return 0; }

    若catch中没有sleep,会卡死。子进程报完树后执行完kill(ppid,SIGUSR2),父进程开始报数,然后发送SIGUSR1给子进程,子进程报数,flag置为1,然后从kill(ppid,SIGUSR2)之后执行指令,flag=0,不会给父进程发送信号了。

    另一种方法:

    #include <stdio.h>
    #include <unistd.h>
    #include <signal.h>
    
    //int flag=0;
    int count;
    pid_t pid;
    
    void cat_son(int num){
        //sleep(1);
        printf("%d
    ", count);
        count+=2;
        //flag=1;
        kill(getppid(),SIGUSR2);
    }
    
    void cat_father(int num){
        //sleep(1);
        printf("%d
    ", count);
        count+=2;
        //flag=1;
        kill(pid,SIGUSR1);
    }
    
    int main()
    {
        pid=fork();
        if(pid==0){
            count=1;
            pid_t ppid=getppid();
            signal(SIGUSR1,cat_son);
            while(1){
                //if(flag==1){
                  //  kill(ppid,SIGUSR2);
                   // flag=0;
                //}
            }
        }else{
            sleep(1);
            count=2;
            signal(SIGUSR2,cat_father);
            kill(pid,SIGUSR1);
            while(1){
                //if(flag==1){
                   // kill(pid,SIGUSR1);
                    //flag=0;
                //}
            }
        }
    
        return 0;
    }
  • 相关阅读:
    RABBITMQ/JAVA 客户端测试(再补:利用文件流)
    在虚拟机中安装CentOS7
    RabbitMQ/JAVA 客户端测试(补:利用线程)
    ffmepg-nginx-nginx-rtmp-module配置脚本
    PDO防注入原理分析以及使用PDO的注意事项
    使用MySQL Proxy解决MySQL主从同步延迟
    好文收藏
    CentOS6.6安装mysql出现的问题
    大型网站技术架构相关文章
    Redis必要的一些配置
  • 原文地址:https://www.cnblogs.com/FEIIEF/p/12500462.html
Copyright © 2011-2022 走看看