Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/60.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 使用管道的进程间通信_C_Fork_Pipe_Deadlock_File Descriptor - Fatal编程技术网

C 使用管道的进程间通信

C 使用管道的进程间通信,c,fork,pipe,deadlock,file-descriptor,C,Fork,Pipe,Deadlock,File Descriptor,祖父过程应该经过从3到N-1的数字。通过管道(filedes)将每个数字发送给父亲。 父亲应该检查管道的内容物,并为管道中的每个数字计算一些东西。如果结果为正,则创建子项以进一步计算它。孩子们应该把他们的结果写进给祖父的管道(filedes1)。祖父在和父亲交流之前应该检查一下管道 简言之: Grandfather - sends data to Father Father sends data to Children Children send data to Grandfather #in

祖父过程应该经过从3到N-1的数字。通过管道(filedes)将每个数字发送给父亲。 父亲应该检查管道的内容物,并为管道中的每个数字计算一些东西。如果结果为正,则创建子项以进一步计算它。孩子们应该把他们的结果写进给祖父的管道(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;
}
祖父-向父亲发送数据
父亲给孩子们发送数据
孩子们向祖父发送数据
#包括
#包括
#包括
#包括
#包括
#定义n20
int-pid[N],子节点号=0;
intprim(intm)
{
int i;
对于(i=2;i其他
filedes2[2],//父->子
filedes3[2];//孩子->爷爷
//pid[N],,i=0

如果(管道(filedes1)程序卡在

            check=read(filedes1[0],&n,sizeof(n));
由于没有人在写入
filedes1[1]
。如果您注释掉该行,程序将运行到完成

另外,请加上几行

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

到文件。
unistd.h
用于
pipe
fork
sys/wait。h
用于
waitpid
程序被卡住

            check=read(filedes1[0],&n,sizeof(n));
由于没有人在写入
filedes1[1]
。如果您注释掉该行,程序将运行到完成

另外,请加上几行

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

到文件。
unistd.h
用于
pipe
fork
sys/wait.h
用于
waitpid
这里有几个错误,但我认为您的问题在于

            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
中的中断,因为您确实需要在每次迭代之前读取标记

在子循环后添加一个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);
要写入的第二个参数应该是指针,您给它一个整数。编译器应该对此发出警告。假设您有C99编译器,您可以这样编写:

                        write(filedes3[1],&(int){k*m},sizeof(k*m));
它被称为复合文字,是在C99中添加的

此代码不能随N的增加很好地扩展。您应该等待子任务退出。当您退出时,没有理由使用PID数组。如果想法是并行启动多个任务,则数组大小应为并行任务的最大数量,而不是总任务数


最后,请不要有一个名为
i
的全局设置。这会让几乎所有阅读代码的人感到困惑,可能包括你自己。

这里有几点错误,但我认为你的问题是

            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
中的中断,因为您确实需要在每次迭代之前读取标记

在子循环后添加一个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);
要写入的第二个参数应该是指针,您给它一个整数。编译器应该对此发出警告。假设您有C99编译器,您可以这样编写:

                        write(filedes3[1],&(int){k*m},sizeof(k*m));
它被称为复合文字,是在C99中添加的

此代码不能随N的增加很好地扩展。您应该等待子任务退出。当您退出时,没有理由使用PID数组。如果想法是并行启动多个任务,则数组大小应为并行任务的最大数量,而不是总任务数


最后,请不要使用名为
i
的全局设置。这会让阅读代码的几乎所有人感到困惑,可能包括你自己。

waitpid(getppid()…
可能是我见过的最奇怪的事情。你认为这有什么作用?(有更简单的方法将errno设置为ECHILD)@Williampesell我以为祖父先于父亲离开。但事实并非如此。我的问题是我没有正确使用管道。在写入
filedes1
之前,你正在阅读
filedes3
。这没有任何意义。@Per Johansson我跳过了3,因为那里没有任何东西,但它会停在4,即使我在管道中死记硬背6,9,12,15,18。它不会将它们写入管道。只是检查。抱歉。
waitpid(getppid()…
可能是我见过的最奇怪的事情。你认为这有什么作用?(有更简单的方法将errno设置为ECHILD)@Williampesell我以为祖父先于父亲离开。但事实并非如此。我的问题是我没有正确使用管道。在写入
filedes1
之前,你正在阅读
filedes3
。这没有任何意义。@Per Johansson我跳过了3,因为那里没有任何东西,但它会停在4,即使我在管道中死记硬背6,9,12,15,18。它不会将它们写入管道。只是检查。抱歉。是的,但注释并不能解决问题。我也可以从4开始在祖父中启动for循环,因为在3时没有孙子写过任何东西。但在4时它会再次暂停。我需要一种方法,使进程以正确的顺序访问管道。@TanatosDaniel,我没有看到与您描述的代码相对应的代码。在这里,我试图使其仅适用于父亲和祖父。今天下午我将修改代码。@R Sahu抱歉,我之前不清楚。我想发布一个