繁体   English   中英

三个相关进程之间进程间通信的同步

[英]Synchronization of inter process communication between three relative processes

我最近研究了信号的主题以及如何使用它们来帮助同步进程。 我正在尝试写一些像乒乓一样工作的东西。 当有 2 个进程(父和子)时,我可以设法做到,我的代码工作得很好,但是当有 3 个进程(父、子和孙)时,它不起作用,我无法弄清楚我做错了什么,请检查我的代码并帮助我。 如果输入为 10,则输出应如下所示,程序在输入 10 时正常工作,但如果输入为 3、4、5、7、8、9 等,则它不起作用。

孙子 0
儿子 1
父亲 2
儿子 3
孙子 4
儿子 5
父亲 6
儿子 7
孙子 8
儿子 9
父亲 10

编辑:
程序应该做什么:程序中应该创建父/子进程和孙子进程。 这 3 个进程应该只使用一个管道相互通信。 程序等待用户输入正整数。 根据这个输入,这3个进程应该一一打印出一个从0开始的数字。例如,如果输入是10,那么这些进程应该打印从0到1,每个进程只打印一个数字,然后加1。 孙子打印出第一个数字。 他首先打印 0 并使用管道通道发送下一个数字来处理孩子。 进程子打印,将数字增加一并将其发送到父进程。 父进程打印数字,将其增加一并将其发送给子进程。 一直这样,直到其中之一达到用户输入的数字。

对于输入 1,3,5,7,9 我的程序打印到 2,4,6,8,10 包括这些数字,这是不正确的。 对于输入 4,8,我的程序打印到数字 4 和 8,但一直等待并且不返回任何内容。

#include <stdio.h>
#include <unistd.h>
#include <signal.h>
#include <sys/types.h>
#include <sys/wait.h>

volatile int flag = 0;

void SigHandler(int s)
{
    signal(SIGUSR1, SigHandler);
    flag = 1;
}

int main()
{
    pid_t pid;
    int fd[2];
    int count=0, countMax, queue=0;
    scanf("%d",&countMax);

    signal(SIGUSR1, SigHandler);

    if(pipe(fd) < 0)
    {
        perror("pipe\n");
        return 1;
    }

    if((pid=fork()) < 0)
    {
        perror("fork\n");
        return 2;
    }
    else if(pid == 0)
    {
        //SON
        pid = fork();
        if(pid<0)
        {
            perror("fork\n");
            return 3;
        }
        else if(pid == 0)
        {
            //GRANDSON
            while(count < countMax)
            {
                if(!flag)
                    pause();
                flag = 0;
                read(fd[0], &count, sizeof(int));
                printf("grandson %d\n", count++);
                fflush(stdout);
                write(fd[1], &count, sizeof(int));
                kill(getppid(), SIGUSR1);
            }
            close(fd[0]);
            close(fd[1]);
            return 0;
        }
        else
        {
        //SON
            flag = 0;
            kill(pid, SIGUSR1);
            while(count < countMax)
            {
                if(!flag)
                    pause();
                flag = 0;
                read(fd[0], &count, sizeof(int));
                printf("son %d\n", count++);
                fflush(stdout);
                write(fd[1], &count, sizeof(int));
                if(queue == 0)
                {
                    kill(getppid(), SIGUSR1);
                    queue = 1;
                }
                else
                {
                    kill(pid, SIGUSR1);
                    queue = 0;
                }
            }
            close(fd[0]);
            close(fd[1]);
            return 0;
        
        }
    }
    else
    {
    //FATHER
        write(fd[1], &count, sizeof(int));
        kill(pid,SIGUSR1);
        fflush(stdout);
            while(count < countMax)
            {
                if(count>=countMax)
                    raise(SIGINT);
                if(!flag)
                    pause();
                flag = 0;
                read(fd[0], &count, sizeof(int));
                printf("father %d\n", count++);
                fflush(stdout);
                write(fd[1], &count, sizeof(int));
                kill(pid, SIGUSR1);
            }
        close(fd[0]);
        close(fd[1]);
        return 0;
    }
}

我在程序中添加了一些调试输出

#include <stdio.h>
#include <unistd.h>
#include <signal.h>
#include <sys/types.h>
#include <sys/wait.h>

volatile int flag = 0;

void SigHandler(int s)
{
    signal(SIGUSR1, SigHandler);
    flag = 1;
}

int main()
{
    pid_t pid;
    int fd[2];
    int count=0, countMax, queue=0;
    setvbuf(stderr, NULL, _IONBF, 0);
    printf("enter maximum count: ");
    scanf("%d",&countMax);

    signal(SIGUSR1, SigHandler);

    if(pipe(fd) < 0)
    {
        perror("pipe\n");
        return 1;
    }

    if((pid=fork()) < 0)
    {
        perror("fork\n");
        return 2;
    }
    else if(pid == 0)
    {
        //SON
        pid = fork();
        if(pid<0)
        {
            perror("fork\n");
            return 3;
        }
        else if(pid == 0)
        {
            //GRANDSON
            while(count < countMax)
            {
                if(!flag)
                {
                    fprintf(stderr, "@ grandchild pause\n");
                    pause();
                }
                flag = 0;
                fprintf(stderr, "@ grandchild read (after pause)\n");
                read(fd[0], &count, sizeof(int));
                printf("grandson %d\n", count++);
                fflush(stdout);
                write(fd[1], &count, sizeof(int));
                fprintf(stderr, "@ grandchild signal child\n");
                kill(getppid(), SIGUSR1);
            }
            fprintf(stderr, "@ grandchild done\n");
            close(fd[0]);
            close(fd[1]);
            return 0;
        }
        else
        {
        //SON
            flag = 0;
            kill(pid, SIGUSR1);
            while(count < countMax)
            {
                if(!flag)
                {
                    fprintf(stderr, "- child pause\n");
                    pause();
                }
                flag = 0;
                fprintf(stderr, "- child read (after pause)\n");
                read(fd[0], &count, sizeof(int));
                printf("son %d\n", count++);
                fflush(stdout);
                write(fd[1], &count, sizeof(int));
                if(queue == 0)
                {
                    fprintf(stderr, "- child signal parent\n");
                    kill(getppid(), SIGUSR1);
                    queue = 1;
                }
                else
                {
                    fprintf(stderr, "- child signal grandchild\n");
                    kill(pid, SIGUSR1);
                    queue = 0;
                }
            }
            fprintf(stderr, "- child done\n");
            close(fd[0]);
            close(fd[1]);
            return 0;
        
        }
    }
    else
    {
    //FATHER
        write(fd[1], &count, sizeof(int));
        kill(pid,SIGUSR1);
        fflush(stdout);
            while(count < countMax)
            {
                if(count>=countMax)
                {
                    fprintf(stderr, "# parent raise SIGINT\n");
                    raise(SIGINT);
                }
                if(!flag)
                {
                    fprintf(stderr, "# parent pause\n");
                    pause();
                }
                flag = 0;
                fprintf(stderr, "# parent read (after pause)\n");
                read(fd[0], &count, sizeof(int));
                printf("father %d\n", count++);
                fflush(stdout);
                write(fd[1], &count, sizeof(int));
                fprintf(stderr, "# parent signal child\n");
                kill(pid, SIGUSR1);
            }
        fprintf(stderr, "# parent done\n");
        close(fd[0]);
        close(fd[1]);
        return 0;
    }
}

使用输入4我得到这个输出:

enter maximum count: 4                                                                                                                           
# parent pause                                                                                                                                   
- child pause                                                                                                                                    
@ grandchild read (after pause)                                                                                                                  
grandson 0                                                                                                                                       
@ grandchild signal child                                                                                                                        
@ grandchild pause                                                                                                                               
- child read (after pause)                                                                                                                       
son 1                                                                                                                                            
- child signal parent                                                                                                                            
- child pause                                                                                                                                    
# parent read (after pause)                                                                                                                      
father 2                                                                                                                                         
# parent signal child                                                                                                                            
# parent pause                                                                                                                                   
- child read (after pause)                                                                                                                       
son 3                                                                                                                                            
- child signal grandchild                                                                                                                        
- child done                                                                                                                                     
@ grandchild read (after pause)                                                                                                                  
grandson 4                                                                                                                                       
@ grandchild signal child                                                                                                                        
@ grandchild done                                                                                                                                

如您所见,最后孩子已经离开了循环。 孙子尝试向将不再反应的子进程发送信号,并且父进程在pause等待信号,但没有进程会向父进程发送信号。

此行为取决于输入值。

编辑

可以在 Tevfik Oğuzhan AKSOY 的回答中找到解决此处显示问题的原始程序的修改版本。

#include <stdio.h>
#include <unistd.h>
#include <signal.h>
#include <sys/types.h>
#include <sys/wait.h>

volatile int flag = 0;

void SigHandler(int s)
{
    signal(SIGUSR1, SigHandler);
    flag = 1;
}

int main()
{
    pid_t pid;
    pid_t pidFather = getpid();
    int fd[2];
    int count=0, countMax, queue=0;
   
    scanf("%d",&countMax);

    signal(SIGUSR1, SigHandler);

    if(pipe(fd) < 0)
    {
        perror("pipe\n");
        return 1;
    }

    if((pid=fork()) < 0)
    {
        perror("fork\n");
        return 2;
    }
    else if(pid == 0)
    {
        //SON
        pid = fork();
        if(pid<0)
        {
            perror("fork\n");
            return 3;
        }
        else if(pid == 0)
        {
            //GRANDSON
            while(count < countMax)
            {
                if(!flag)
                {
                    pause();
                }
                flag = 0;
                read(fd[0], &count, sizeof(int));
        if(count<=countMax)
        {
                    printf("grandson %d\n", count++);
                    fflush(stdout);
                    write(fd[1], &count, sizeof(int));
            kill(getppid(), SIGUSR1);
        }
            }
            close(fd[0]);
            close(fd[1]);
            return 0;
        }
        else
        {
            //SON
            flag = 0;
            kill(pid, SIGUSR1);
            while(count < countMax)
            {
                if(!flag)
                {
                    pause();
                }
                flag = 0;
                read(fd[0], &count, sizeof(int));
        if(count<=countMax)
        {
                    printf("son %d\n", count++);
                    fflush(stdout);
                    write(fd[1], &count, sizeof(int));
                    if(queue == 0)
                    {
                                kill(getppid(), SIGUSR1);
                            queue = 1;
                    }
                    else if(queue != 0)
                {
                        kill(pid, SIGUSR1);
                        queue = 0;
                    }
        }
            }
        kill(getppid(), SIGUSR1);
            close(fd[0]);
            close(fd[1]);
            return 0;
        }
    }
    else
    {
        //FATHER
    write(fd[1], &count, sizeof(int));
        kill(pid,SIGUSR1);
        fflush(stdout);
        while(count < countMax)
        {
            if(!flag)
            {
                pause();
            }
            flag = 0;
            read(fd[0], &count, sizeof(int));
        if(count<=countMax)
        {
            printf("father %d\n", count++);
            fflush(stdout);
                write(fd[1], &count, sizeof(int));
                kill(pid, SIGUSR1);
        }
        }
        close(fd[0]);
    close(fd[1]);
        return 0;
    }
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM