zoukankan      html  css  js  c++  java
  • Linux Linux程序练习十六(进程间的通信信号版)

    /*
     * 题目:
     * 编写程序,要去实现如下功能:
     父进程创建子进程1和子进程2、子进程1向子进程2发送可靠信号,并传送额外数据为子进程1的pid*2;
     子进程2接受可靠信号的值,并发送给父进程,父进程把接受的值进行打印。
     提示:用sigqueue和sigaction实现
     * */
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <unistd.h>
    #include <errno.h>
    #include <sys/types.h>
    #include <sys/wait.h>
    #include <signal.h>
    
    /*
     * 父进程中,知道所有子进程的pid,所以父进程向子进程1发送带数据的信号,数据是子进程2的pid
     * 子进程1向子进程2发送信号,子进程2向父进程发送信号
     * */
    
    //子进程1信号安装回调函数
    void handler1(int sign, siginfo_t * info, void *p)
    {
        if (sign == SIGRTMIN)
        {
            printf("子进程1接收到父进程发送的数据:子进程2的pid=%d
    ", info->si_value.sival_int);
            //向子进程2发送带数据的信号
            union sigval v1;
            v1.sival_int = getpid() * 2;
            if (sigqueue(info->si_value.sival_int, SIGRTMIN,v1) != 0)
            {
                perror("sigqueue() err");
                return;
            }
            //退出子进程1
            printf("子进程1 quit
    ");
            exit(0);
        }
        printf("子进程1接收到其他信号");
    }
    
    //子进程2信号安装回调函数
    void handler2(int sign, siginfo_t * info, void *p)
    {
        if (sign == SIGRTMIN)
        {
            printf("子进程2接收到数据%d
    ", info->si_value.sival_int);
            //向父进程发送信号
            if (sigqueue(getppid(), SIGRTMIN, info->si_value) != 0)
            {
                perror("sigqueue() err");
                return;
            }
            //退出子进程2
            printf("子进程2 quit
    ");
            exit(0);
    
        }
    }
    
    //父进程信号安装回调函数
    void handlerf(int sign, siginfo_t * info, void *p)
    {
        if (sign == SIGRTMIN)
        {
            //打印信号值
            printf("父进程接收的值是%d
    ", info->si_value.sival_int);
            printf("game is over!
    ");
            exit(0);
        }
    }
    
    int main(int arg, char *args[])
    {
        pid_t pid = 0;
        pid = fork();
        if (pid == -1)
        {
            perror("fork() err");
            return -1;
        }
        if (pid == 0)
        {
            //子进程1
            printf("子进程1的pid=%d
    ",getpid());
            //安装信号SIGRTMIN,等待父进程发送信号
            struct sigaction act;
            act.sa_sigaction = handler1;
            sigemptyset(&act.sa_mask);
            act.sa_flags = SA_SIGINFO;
            if (sigaction(SIGRTMIN, &act, NULL) != 0)
            {
                printf("sigaction() failed !
    ");
                exit(0);
            }
            //等待父进程发送信号
            printf("子进程1等待父进程发送信号
    ");
            while (1)
            {
                printf("子进程1 sleep
    ");
                sleep(1);
            }
        }
        if (pid > 0)
        {
            //存储子进程1的pid
            pid_t pid_1 = pid;
            pid = fork();
            if (pid == -1)
            {
                perror("fork() err");
                exit(0);
            }
            if (pid == 0)
            {
                //子进程2
                printf("子进程2的pid=%d
    ",getpid());
                //安装信号SIGRTMIN,等待子进程1发送信号
                struct sigaction act;
                act.sa_sigaction = handler2;
                sigemptyset(&act.sa_mask);
                act.sa_flags = SA_SIGINFO;
                if (sigaction(SIGRTMIN, &act, NULL) != 0)
                {
                    printf("sigaction() failed !
    ");
                    exit(0);
                }
                //等待子进程1发送信号
                printf("子进程2等待子进程1发送信号
    ");
                while (1)
                {
                    printf("子进程2 sleep
    ");
                    sleep(1);
                }
            } else if (pid > 0)
            {
                //父进程
                printf("父进程的pid=%d
    ",getpid());
                //安装信号SIGRTMIN,等待子进程2发送信号
                struct sigaction act;
                act.sa_sigaction = handlerf;
                sigemptyset(&act.sa_mask);
                act.sa_flags = SA_SIGINFO;
                if (sigaction(SIGRTMIN, &act, NULL) != 0)
                {
                    printf("sigaction() failed !
    ");
                    exit(0);
                }
                sleep(5);
                //向子进程1发送信号
                printf("父进程向子进程1发送信号
    ");
                union sigval v1;
                v1.sival_int = pid;
                if (sigqueue(pid_1, SIGRTMIN, v1) != 0)
                {
                    perror("sigqueue() err");
                    exit(0);
                }
                int ret = 0;
                //等待子进程退出
                while (1)
                {
                    ret = wait(NULL);
                    if (ret == -1)
                    {
                        if (errno == EINTR)
                        {
                            continue;
                        }
                        break;
                    }
                }
                //等待信号到达
                while (1)
                {
                    sleep(1);
                }
            }
        }
        return 0;
    }
    
    /*
     * 错误总结:执行该程序,发现子进程1老是出不来,开始我以为是fork()失败,经过注释代码调试
     * 发现问题出现在父进程的发送信号这个函数上,原因是父进程发送信号的时候,,子进程1刚被创建,还没有执行安装信号函数
     * 而信号SIGRTMIN的默认行为是终止进程,所以子进程刚被创建好了,就被终止了
     *
     * 实际上还有一种方法,可以在fork()之前安装3个不同的信号,3个进程分别接收不同的信号加以处理
     * */
  • 相关阅读:
    python 成功解决import librosa出错问题
    音频属性详解(入门解读)
    如何用python将txt中的package批量安装
    python生成一个WAV文件的正弦波
    图像处理方法(膨胀腐蚀,霍夫变换,滤波,去噪,图像增强,二值化,图片旋转,画直线)
    ORACLE数据库学习笔记1
    SICP:构造数据抽象--数据结构中队列与树的解释
    SICP:构造过程抽象--面向对象的解释
    Java学习笔记--文件IO
    Java学习笔记--异常机制
  • 原文地址:https://www.cnblogs.com/zhanggaofeng/p/6123965.html
Copyright © 2011-2022 走看看