2014-10-10 86 views
0

我的程序编程教师让我编写一个关于C的程序,创建四个孩子并使他们计算出第一,第二,第三和第四季度分别是一系列数字,给父母所有的素数。当两个子进程都通过管道与父进程通信时,一个子进程阻塞了另一个子进程

我正确地编码了第一个孩子季度,但是当我添加第二个孩子时,程序的行为变得不可调整。我的老师和我花了大约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可以写在管道上,并从父母那里读取,以及为什么第二个孩子完成封锁第一个孩子。

问候。

回答

0

在第67行,您的代码出现了第二个switch语句(第45行)。执行继续在第77行。因此,子进程2试图关闭(fd2 [1])两次。子进程2正在执行父进程的目标代码。

你可以尝试用

exit(0); 
+0

更换线67谢谢你,你的解决方案工作正常。无论如何,我想知道250000的出现位置,如果你能告诉我。 – 2014-10-10 12:23:08

+0

建议你写布尔函数isPrime( – 2014-10-10 13:01:30

+0

建议你写布尔函数isPrime(long candidatePrime,long testDenominator)。最好使用素数列表,不是每个数字。最大testDenominator是sqrt(candidatePrime) - note sqrt是double,not长在ansi c。 – 2014-10-10 13:07:00