祖父过程应该经过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;
}
答案 0 :(得分:2)
程序停留在
check=read(filedes1[0],&n,sizeof(n));
因为没有人写信给filedes1[1]
。如果您注释掉该行,程序将运行至完成。
P.S。请添加行
#include <unistd.h>
#include <sys/wait.h>
到文件。 unistd.h
和pipe
需要fork
。 sys/wait.h
需要waitpid
。
答案 1 :(得分:2)
这里有几个问题,但我认为你的问题是
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时无法很好地扩展。您应该{Child} wait
退出。当你这样做时,没有理由使用一系列的pids。如果想要并行启动多个任务,则阵列大小应该是并行任务的最大数量,而不是总任务的数量。
最后,请不要有一个全球名为i
。这会让每个人都在阅读代码时感到困惑,可能包括你自己。