简体   繁体   中英

Synchronization of inter process communication between three relative processes

I've recently studied the topic of signals and how to use them to help synchronize the processes. I'm trying to write something that will work like Ping-Pong. When there are 2 processes(Parent and Child), i can manage to do it and my code works just fine but when there are 3 processes(Parent, Child and Grandchild), it just doesn't work and i can't figure out what I'm doing wrong, please check my code and help me. The output should look like this if the input is 10, the program works as it should for the input of 10, however it doesn't work if the input is for example 3,4,5,7,8,9 etc.

grandson 0
son 1
father 2
son 3
grandson 4
son 5
father 6
son 7
grandson 8
son 9
father 10

EDIT:
What the program should do: There should be created parent/child and grandchild processes in the program. These 3 processes should communicate with each other using only one pipe. The program waits for a positive integer input from the user. According to this input, these 3 processes one by one should print out a number starting from 0. For example, if the input is 10, the processes should print from 0 to 1 with printing just one number each and increase it by one. Grandson prints out the first number. He prints 0 first and using the pipe channel he sends the next number to process child. Process child prints, increases the number by one and sends it to the parent process. Parent process prints the number, increases it by one and sends it to the child process. Like this until one of them reaches the number which was input by the user.

For inputs 1,3,5,7,9 my program prints till 2,4,6,8,10 including these numbers, which is not correct. For inputs 4,8 my program prints till numbers 4 and 8, but keeps waiting and doesn't return anything.

#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;
    }
}

I added some debug output to the program

#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;
    }
}

With input 4 I get this output:

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                                                                                                                                

As you can see, at the end the child has already left the loop. The grandchild tries to send a signal to the child which will no longer react, and the parent is waiting for a signal in pause , but no process will send a signal to the parent.

This behavior depends on the input value.

Edit

A modified version of the original program which fixes the problem shown here, can be found in Tevfik Oğuzhan AKSOY's answer .

#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;
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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