C - 子进程等待另一个进程完成,main() 没有执行到最后



fork()4 个子进程时,我在第一个子进程执行后进入wait(),下一个子进程甚至没有被执行。我不确定为什么会出现这种现象。我不是分叉专家,每个提示都值得赞赏。

Input data: ./forkexample 2 3 4 5

这是我的代码:

#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
int main(int argc, const char **argv)
{
if (argc != 5)
{
printf("Argument # is invalid. %s < 4n", argv[0]);
exit(1);
}
float a = atof(argv[1]);
float b = atof(argv[2]);
float c = atof(argv[3]);
float d = atof(argv[4]);
if ((a == 0.0) || (b == 0.0) || (c == 0.0) || (d == 0.0))
{
printf("Conversion error, invalid parameters!n");
exit(1);
}
int ossz[2], kiv[2], szor[2], oszt[2];
int mainpid;
if ((pipe(ossz) < 0))
perror("pipe error(/)");
if ((pipe(kiv) < 0))
perror("pipe error(*)");
if ((pipe(szor) < 0))
perror("pipe error(-)");
if ((pipe(oszt) < 0))
perror("pipe error(*)");
mainpid = getpid();
pid_t osszeg, kivonas, szorzat, hanyados;
//            (a+b*c) / (a-b+d-c) + a*b*c*d;
//       *****************************+***********************************
if ((osszeg = fork()) == 0)
{
if (mainpid != getpid())
{ //osszeadast vegez el
float b1, c1, byteb1, bytec1;
byteb1 = read(ossz[0], &b1, sizeof(float));
printf("%d  Osszeg read in %.2fn", getpid(), b1);
bytec1 = read(ossz[0], &c1, sizeof(float));
printf("%d Osszeg read in %.2fn", getpid(), c1);
close(ossz[0]);
c1 += b1;
write(ossz[1], &c1, sizeof(float));
printf("%d Osszeadas wrote %.2fn", getpid(), c1);
}
else if (getpid() < 0)
{
printf("Error creating children process, cprog stops!n");
exit(1);
}
}
//       *****************************-***********************************
if ((kivonas = fork()) == 0)
{
if (mainpid != getpid())
{ //kivonast vegez el
float b2, c2, byteb2, bytec2;
byteb2 = read(kiv[0], &b2, sizeof(float));
printf("%d Kivonas read in %.2fn", getpid(), b2);
bytec2 = read(kiv[0], &c2, sizeof(float));
printf("%d Kivonas read in %.2fn", getpid(), c2);
close(kiv[0]);
c2 -= b2;
write(kiv[1], &c2, sizeof(float));
printf("%d Kivonas wrote %.2fn", getpid(), c2);
}
else if (getpid() < 0)
{
printf("Error creating children process, cprog stops!n");
exit(1);
}
}
//       ***************************** Multiplication***********************************
if ((szorzat = fork()) == 0)
{
if (mainpid != getpid())
{ //szorzast vegez el
float b3, c3, byteb3, bytec3;
byteb3 = read(szor[0], &b3, sizeof(float));
printf("%d Szorzat read in %.2fn", getpid(), b3);
bytec3 = read(szor[0], &c3, sizeof(float));
printf("%d Szorzat read in %.2fn", getpid(), c3);
close(szor[0]);
c3 *= b3;
write(szor[1], &c3, sizeof(float));
printf("%d Szorzat wrote %.2fn", getpid(), c3);
}
else if (getpid() < 0)
{
printf("Error creating children process, cprog stops!n");
}
}
//       *****************************Division***********************************
if ((hanyados = fork()) == 0)
{
if (mainpid != getpid())
{ //osztast vegez el
float b4, c4, byteb4, bytec4;
byteb4 = read(oszt[0], &b4, sizeof(float));
printf("%d Oszto read in %.2fn", getpid(), b4);
bytec4 = read(oszt[0], &c4, sizeof(float));
printf("%d Oszto read in %.2fn", getpid(), c4);
close(oszt[0]);
c4 = c4 / b4;
write(oszt[1], &c4, sizeof(float));
printf("%d Oszto wrote %.2fn", getpid(), c4);
}
else if (getpid() < 0)
{
printf("Error creating children process, cprog stops!n");
exit(1);
}
}
float szorzaser, osztaser, kivonaser, osszeger, vegeredmeny;
write(szor[1], &b, sizeof(float));
write(szor[1], &c, sizeof(float));
wait(NULL);
read(szor[0], &szorzaser, sizeof(float)); //b*c
printf("%d Parent got: %.2f /n", getpid(), szorzaser);
write(ossz[1], &a, sizeof(float));
write(ossz[1], &szorzaser, sizeof(float));
wait(NULL);
read(ossz[0], &osszeger, sizeof(float)); //a+szorzaser(b*c)
printf("%d Parent got: %.2f /n", getpid(), osszeger);
//***********************a+b*c**********************************************
write(ossz[1], &b, sizeof(float));
write(ossz[1], &d, sizeof(float));
wait(NULL);
read(ossz[0], &osszeger, sizeof(float)); //b+d
printf("%d Parent got: %.2f /n", getpid(), osszeger);
write(kiv[1], &a, sizeof(float));
write(kiv[1], &osszeger, sizeof(float));
wait(NULL);
read(kiv[0], &kivonaser, sizeof(float)); //a-osszeger(b+d)
printf("%d Paren  t got: %.2f /n", getpid(), kivonaser);
write(kiv[1], &kivonaser, sizeof(float));
write(kiv[1], &c, sizeof(float));
wait(NULL);
read(kiv[0], &kivonaser, sizeof(float)); //kivonaser(a-b+d-c)
printf("%d Parent got: %.2f /n", getpid(), kivonaser);
write(oszt[1], &kivonaser, sizeof(float));
write(oszt[1], &osszeger, sizeof(float)); //betesszuk az osztas pipejaba
wait(NULL);
read(oszt[0], &osztaser, sizeof(float)); //(a+b*c) / (a-b+d-c)
printf("%d Parent got: %.2f /n", getpid(), osztaser);
//*************************(a-b+d-c)*********************************************
write(szor[1], &a, sizeof(float));
write(szor[1], &b, sizeof(float));
wait(NULL);
read(szor[0], &szorzaser, sizeof(float)); //a*b
printf("%d Parent got: %.2f /n", getpid(), szorzaser);
write(szor[1], &szorzaser, sizeof(float));
write(szor[1], &c, sizeof(float));
wait(NULL);
read(szor[0], &szorzaser, sizeof(float)); //a*b*c
printf("%d Parent got: %.2f /n", getpid(), szorzaser);
write(szor[1], &szorzaser, sizeof(float));
write(szor[1], &c, sizeof(float));
wait(NULL);
read(szor[0], &szorzaser, sizeof(float)); //a*b*c*d
printf("%d Parent got: %.2f /n", getpid(), szorzaser);
//************************* a*b*c*d *********************************************
write(ossz[1], &osztaser, sizeof(float));
write(ossz[1], &szorzaser, sizeof(float));
wait(NULL);
read(ossz[0], &vegeredmeny, sizeof(float)); //(a+b*c) / (a-b+d-c)+ a*b*c*d;
printf("%d Parent got: %.2f /n", getpid(), vegeredmeny);
close(ossz[0]);
close(ossz[1]);
close(kiv[0]);
close(kiv[1]);
close(szor[0]);
close(szor[1]);
close(oszt[0]);
close(oszt[1]);
printf("%d got the final result: %.2f!n", getpid(), vegeredmeny);
return (0);
}

整个过程尝试使用子进程计算(a+b*c)/(a-b+d-c)+a*b*c*d。编译并运行此序列后,将运行:

vargaelod23@vargaelod23-M5400:~/LinuxI/fork$ ./fork1 2 3 4 5
5459 Szorzat read in 3.00
5459 Szorzat read in 4.00
5459 Szorzat wrote 12.00

在此之后,计算等待一些东西,我不知道为什么。

子进程不会退出,但会继续运行用于父进程的代码。因此,在第一个子进程将其结果写入管道后,它开始分叉另一个子进程,然后再次写入自己的管道并输入wait()。然后你有一个死锁 - 父进程等待第一个子进程退出,第一个子进程等待其子进程退出。

您也不会检查任何write()调用的错误条件。如果这样做,您将看到正在发出意外的write()调用。

向子路径添加_exit()调用应该会有所帮助,但此代码中还有许多其他错误。

最新更新