簡體   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