当两个子流程都通过管道与父流程进行通信时,一个子流程会阻止另一个子流程

时间:2014-10-10 10:47:26

标签: c fork pipe

我的流程编程老师让我在C上编写了一个程序,它创建了四个孩子并让他们分别计算一系列数字的第一,第二,第三和第四个四分之一,给父母他们所有的素数。 / p>

我正确编码了第一个子季度,但是当我添加第二个孩子时,程序的行为无法控制。我的老师和我花了大约2个小时查看代码的深度,但我们没有发现问题。

代码是这样的,因为我现在拥有它:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void main(){

    unsigned long long a=500000,b,c; // not used yet -> d,e,i;
    pid_t pid1;
    unsigned long long fin = 0; //This is used in each child to write if it has finished the prime number calculation.
    unsigned long long fin1 = 0, fin2 = 0; //This is used on the parent to check if a child has finished.
    int primo = 0; //This is used to know if a number is a prime number.
int fd1[2]; //Pipe which communicates the parent with the first child.
    int fd2[2]; //Pipe which communicates the parent with the second child.
//  int fd3[2]; //Not used yet
//  int fd4[4]; //Not used yet
    pipe(fd1); //First child pipe
    pipe(fd2); //Second child pipe
//  pipe(fd3); //Not used yet
//  pipe(fd4); //Not used yet
    pid1 = fork(); //Creating first child
        switch (pid1){
            case -1: //Error
                printf("Error creating child.");
                exit(-1);
            case 0: //First child
                close(fd1[0]); //Input close
                for(b=100;b<(a/4);b++){         //
                    for(i=2;i<b/2;i++){     // These loops check each number from 100 to 125000
                        if(b%i==0){     // and if it is NOT a prime number, it breaks and tries
                            primo=0;    // to check the next number.
                            break;      //                  
                        }           //
                        primo=1;        //      
                    }
                    if(primo==1){               //If it IS a prime number, it's written on the pipe
                        write(fd1[1], &b, sizeof(b));   //and sent to the parent.
                    }
                }
                fin=1; //The child sets it has finished calculating and writes it in the pipe to tell his parent.
                write(fd1[1], &fin, sizeof(fin));
                close(fd1[1]); //Output closing
                break; //First child ends
            default: //Parent

                pid1 = fork(); //Creating second child
                    switch (pid1) {

                        case -1: //error
                            printf("Error");
                            exit(-1);
                        case 0: //Sencond child
                            close(fd2[0]);                      //This behavior is EXACTLY equals to the first child behavior
                            for(c=(a/4);c<(a/2);c++){               //
q                               for(i=2;i<c/2;i++){             //
                                    if(c%i==0){             //
                                        primo=0;            //
                                        break;              //
                                    }                   //
                                primo=1;                    //
                                }                       //
                                if(primo==1){                   //
                                    write(fd2[1], &c, sizeof(c));       //
                                }                       //
                            }                           //
                            fin=1;                          //
                            write(fd2[1], &fin, sizeof(fin));           //
                            close(fd2[1]);                      //
                            break;                              
                        default: //Parent           
                            //HERE WOULD COME THE CODE FOR THIRD AND FOURTH CHILDS.
                            break;



                    } //second child switch close

                //Parent reads answers from childs
                close(fd1[1]); //First child output closing
                close(fd2[1]); //Second child output closing
                for(;;){ //Infinite loop
                    if(fin1==0){ //If first child HAS NOT finished (As it sends a 1 if it does)
                        read(fd1[0], &b, sizeof(b)); //Read the prime number
                        if(b==1){ //If it is a 1, then the child has finished.
                            fin1=1;  //We set the first child has finished
                            close(fd1[0]); //First child input closing
                        }else{
                            printf("%llu es primo\n", b); //Otherwise it is a prime number, then it's printed to console.
                        }   
                    }   
                    if(fin2==0){                        //Same behavior as with first child
                        read(fd2[0], &c, sizeof(c));
                        if(c==1){
                            fin2=1;
                            close(fd2[0]);
                        }else{
                            printf("%llu es primo\n", c);
                        }   
                    }
                    if(fin1==1&&fin2==1){ //If both childs have finished, then we exit.
                        exit(0);
                    }                   
                }
                break;

        }
    exit(0);
}

它似乎是正确的,但它无法正常工作。当第二个孩子完成计算其数字范围(从125000到249999)时,它会阻止第一个孩子,第一个孩子就会停止。

然后程序进入读取和打印管道内容的无限循环 它看起来像这样:

[first child last calculated number] es primo
250000 es primo
[first child last calculated number] es primo
250000 es primo
[first child last calculated number] es primo
250000 es primo
[first child last calculated number] es primo
250000 es primo

等等。因此,我们询问如何将250000写入管道并从父母处读取,以及为什么第二个孩子完成阻止第一个孩子。

问候。

1 个答案:

答案 0 :(得分:0)

在第67行,你的代码突破了第二个switch语句(第45行)。执行从第77行恢复。因此子进程2试图关闭(fd2 [1])两次。子进程2正在执行以父进程为目标的代码。

您可以尝试用

替换第67行
exit(0);