C 使用管道的进程间通信
祖父过程应该经过从3到N-1的数字。通过管道(filedes)将每个数字发送给父亲。 父亲应该检查管道的内容物,并为管道中的每个数字计算一些东西。如果结果为正,则创建子项以进一步计算它。孩子们应该把他们的结果写进给祖父的管道(filedes1)。祖父在和父亲交流之前应该检查一下管道 简言之: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
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抱歉,我之前不清楚。我想发布一个