[英]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>
到文件。 pipe
和fork
需要unistd.h
。 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
內的中斷,因為您確實需要閱讀直到標記每次迭代。
在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.