簡體   English   中英

使用管道進行進程間通信

[英]Interprocess communication using pipes

祖父進程的編號應從3到N-1。 將每個數字通過管道(文件)發送給父親。 父親應檢查管道的內容,並為其中的每個數字計算一些內容。 如果結果為正,則創建子項以進一步計算它。 孩子們應將其結果寫入祖父的pipe(filedes1)中。 祖父應在與父親溝通之前檢查管道。

簡而言之:

Grandfather - sends data to Father
Father sends data to Children
Children send data to Grandfather

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

#define N 20

int pid[N],child_no=0;

int prim(int m)
{
    int i;

    for (i=2; i<=m/2; i++)
        if (m%i==0)
            return 0;

    return 1; //prim
}

int check_multiples(int i, int filedes11);

int main()
{
    int filedes1[2], //grandpa->father
        filedes2[2], //father->child
        filedes3[2]; //child->grandpa
        //pid[N],,i=0

    if (pipe(filedes1)<0)
    {
        perror("pipe1");
        exit(EXIT_FAILURE);
    }
    if (pipe(filedes2)<0)
    {
        perror("pipe2");
        exit(EXIT_FAILURE);
    }
    if (pipe(filedes3)<0)
    {
        perror("pipe3");
        exit(EXIT_FAILURE);
    }

    if ((pid[child_no]=fork())<0)
    {
        perror("fork");
        exit(EXIT_FAILURE);
    }
    else
        if (pid[child_no]==0) //father
        {
            int m,v[N],j=0;

            close(filedes1[1]);

            while (read(filedes1[0],&m,sizeof(m)))
            {
                if (prim(m))
                    v[j]=m;

                child_no++;

                if ((pid[child_no]=fork())<0)
                {
                    perror("fork");
                    exit(EXIT_FAILURE);
                }
                else
                    if (pid[child_no]==0)
                    {
                        int k;

                        close(filedes3[0]);
                        for (k=2; k*m<=N; k++)
                        {
                            write(filedes3[1],&(int){k*m},sizeof(k*m));
                            write(filedes3[1], &(int){0}, sizeof(int));
                            exit(0);
                        }
                    }
            }

            int k;
            printf("Prime numbers between 3 and N-1 are: ");
            for (k=0; k<N; k++)
                printf("%d ",v[k]);
            printf("\n");
        }
        else  //grandfather
        {
            int i,m,check=0;

            close(filedes3[1]);
            close(filedes1[0]);
            for (i=3; i<N; i++)
            {
                printf("Checking %d...\n",i);

                if (i!=3)
                {
                    while (read(filedes3[0],&m,sizeof(m))!=0)
                    {
                        printf("%d\n",&m);
                        if (m==0)
                            break;
                        if (i==m)
                        {
                            check=1;
                            break;
                        }
                    }
                }
                printf("Finished checking %d.\n",i);
                if (check==0)
                    write(filedes1[1],&i,sizeof(i));
            }


        }

    return 0;
}

該程序停留在

            check=read(filedes1[0],&n,sizeof(n));

因為沒有人正在寫入filedes1[1] 如果您將該行注釋掉,程序將運行完成。

PS請添加行

#include <unistd.h>
#include <sys/wait.h>

到文件。 pipefork需要unistd.h sys/wait.hwaitpid所必需的。

這里有些錯誤,但是我認為您的問題是

            while (read(filedes3[0],&m,sizeof(m))!=0)

除非關閉文件描述符,否則read不會返回0。 而且它從來沒有關閉過(即使孩子退出,它也一直在父親里面保持打開狀態)。

您應該做的是添加一個特殊的標記,該標記指示列表的末尾並讀取直到獲得該標記。 我建議使用0-1作為標記:

            while (read(filedes3[0],&m,sizeof(m))!=0) {
                if (m == 0)
                    break;

您必須刪除i == m內的中斷,因為您確實需要閱讀直到標記每次迭代。

在Child循環之后,添加一個0寫入。 您可能還應該在那里調用exit

                    ...
                    for (k=2; k*m<=N; k++)
                        write(filedes3[1],&(int){k*m}, sizeof(k*m));
                    write(filedes3[1], &(int){0}, sizeof(int));
                    exit(0);

在其他事情上。 這段代碼實際上並沒有使用filedes2 可能是因為您刪除了一些代碼。 但是,您應該真正在父親內部而不是在祖父內部打開該管道,否則祖父會保留那些我認為不是您想要的fds的副本。

這行是錯誤的:

                        write(filedes3[1],k*m,sizeof(k*m));

要寫入的第二個參數應該是一個指針,並且您要給它一個整數。 您的編譯器應對此發出警告。 假設您有C99編譯器,則可以這樣編寫:

                        write(filedes3[1],&(int){k*m},sizeof(k*m));

它稱為C99中添加的復合文字。

隨着N的增加,此代碼無法很好地擴展。您應該wait Child退出。 當您這樣做時,沒有理由使用PID數組。 如果想法是並行啟動多個任務,則數組大小應為並行任務的最大數量,而不是總任務的數量。

最后,請不要使用名為i的全局i 這會使幾乎所有閱讀代碼的人都感到困惑,包括您自己在內。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM