2012-04-03 12 views
0

Dieses Programm sollte den Wert von 2^1 + 2^2 + ... + 2^10 berechnen:Berechnung Summe von N Befugnisse

#include <stdio.h> 
#include <string.h> 
#include <stdlib.h> 
#include <assert.h> 
#include <stdbool.h> 
#include <unistd.h> 
#include <sys/types.h> 
#include <sys/wait.h> 
#include <signal.h> 
#include <math.h> 

#define N 10 

// sommatoria per i che va da 1 a N di 2^i, ogni processo calcola un singolo valore 

int main(int argc, char** argv) 
{ 
    pid_t figli[N]; 
    unsigned int i; 
    int status; 
    int fd[N][2]; 
    int msg1=0,msg2; 
    int risultato=0; 
    bool padre=true; 
    for(i=0;i<N && padre;i++) 
    { 
     pipe(fd[i]); 
     figli[i]=fork(); 
     if(figli[i]<0) 
     { 
      fprintf(stderr,"Una fork ha fallito\n"); 
     } 
     else if(figli[i]==0) 
     { 
      padre=false; 
     } 
     else 
     { 
      msg1=i+1; 
      write(fd[i][1],&msg1,sizeof(int)); 
     } 
    } 
    if(!padre) 
    { 
     read(fd[i][0],&msg2,sizeof(int)); 
     msg2=pow(2.0,msg2); 
     write(fd[i][1],&msg2,sizeof(int)); 
     exit(0); 
    } 
    else 
    { 
     for(i=0;i<N;i++) 
     { 
      read(fd[i][0],&msg2,sizeof(int)); 
      risultato+=msg2; 
     } 
    } 
    if(padre) 
     fprintf(stderr,"%d\n",risultato); 
    return 0; 
} 

Aber wenn also Xecute das Programm, der Vater Prozess druckt 55 Warum?

+4

Sie versuchen, ein einfaches Problem auf die komplizierteste Weise zu lösen, und sich wundern, warum es nicht funktioniert. Warum versuchst du es nicht einfach? – ugoren

+3

Es riecht als Hausaufgabe –

+0

Deshalb brauchen Sie Mathematik beim Programmieren. – Matt

Antwort

2

Interessanterweise, 55 ist die Summe aller Zahlen von 1 bis 10: Das sollte man einen sofortigen Hinweis geben:

Rohr() erzeugt ein Rohr, einen Kanal unidirektionale Daten, die Dose für die Interprozesskommunikation verwendet werden. Das Array pipefd wird verwendet, um zwei Dateideskriptoren zurückzugeben, die sich auf die Enden der Pipe beziehen. Pipefd [0] bezieht sich auf das Leseende der Pipe. Pipefd [1] bezieht sich auf das Schreibende der Pipe.

Beachten Sie, dass auch: unidirektional. Mit anderen Worten, der Padre liest die gleichen Werte zurück, die er geschrieben hat (daher die 55).

Normalerweise richten Sie zwei Pipes für bidirektionalen Datenverkehr ein, einen für jede Richtung. Also verdopple ich die Anzahl der Pfeifen, benutze sogar solche für Padre-to-Child und Odds für die andere Richtung.

Außerdem fahren Ihre Kinder mit der Padre-Schleife fort, während sie diese Schleife sofort verlassen sollten, so dass ihr Wert i korrekt ist. Sie haben den Loop-Ausgang basierend auf padre, aber dies passiert nachi hat sich geändert. Sie können entweder an der Stelle brechen, an der Sie padre auf false setzen, oder einfach i-- im if(!padre)-Bit, um i auf den korrekten Wert für dieses Kind wiederherzustellen. Ich habe das letztere getan.

Der folgende Code (mit Markierungen zeigen, was geändert) arbeitet in Ordnung:

#include <stdio.h> 
#include <string.h> 
#include <stdlib.h> 
#include <assert.h> 
#include <stdbool.h> 
#include <unistd.h> 
#include <sys/types.h> 
#include <sys/wait.h> 
#include <signal.h> 
#include <math.h> 

#define N 10 

int main(int argc, char** argv) 
{ 
    pid_t figli[N]; 
    unsigned int i; 
    int status; 
    int fd[N*2][2]; // CHANGED: two unidirectional pipes 
    int msg1=0,msg2; 
    int risultato=0; 
    bool padre=true; 
    for(i=0;i<N && padre;i++) 
    { 
     pipe(fd[i*2]); 
     pipe(fd[i*2+1]); // ADDED: create second pipe 
     figli[i]=fork(); 
     if(figli[i]<0) 
     { 
      fprintf(stderr,"Una fork ha fallito\n"); 
     } 
     else if(figli[i]==0) 
     { 
      padre=false; 
     } 
     else 
     { 
      msg1=i+1; 
      write(fd[i*2][1],&msg1,sizeof(int)); // CHANGED: pipe number 
     } 
    } 
    if(!padre) 
    { 
     i--; // ADDED: to restore i for the child 
     read(fd[i*2][0],&msg2,sizeof(int)); // CHANGED: pipe number 
     msg2=pow(2.0,msg2); 
     write(fd[i*2+1][1],&msg2,sizeof(int)); // CHANGED: pipe number 
     exit(0); 
    } 
    else 
    { 
     for(i=0;i<N;i++) 
     { 
      read(fd[i*2+1][0],&msg2,sizeof(int)); // CHANGED: pipe number 
      risultato+=msg2; 
     } 
    } 
    if(padre) 
     fprintf(stderr,"%d\n",risultato); 
    return 0; 
} 

dies die richtige Antwort von 2046 erzeugt, da 20 + 21 + ... 210 = 211 - 1 und, da Sie die Zwei-zu-den-Null Weglassen sind Begriff (gleich 1): 21 + 22 + ... 210 is 211 - 2 (211 = 2048).

2

Das Problem mit dem obigen Code ist, dass die gleiche Pipe zum Schreiben und Lesen nach dem gleichen Prozess verwendet wird. (Hier ist es der Elternprozess).

Das übergeordnete Element übergibt den zu berechnenden Wert an das unter Verwendung von pipe. Das Kind schreibt die Antwort in dieselbe Pipe. Der Elternteil liest das ANS zurück. Hier haben Sie den Fall nicht berücksichtigt: Eltern schreibt Wert in die Pipe und liest die Antwort selbst zurück. Daher hat das Kind nie den Wert bekommen.

Um das oben genannte Problem zu lösen Sie zwei Rohre erstellen müssen: die verschiedenen Rennbedingungen und den Code

  • Rohr vom Kind zum Elternteil
    1. Rohr von Eltern auf das Kind Dadurch wird verhindert, wäre viel besser lesbar. Hier ist der Code, um das Gleiche zu tun. PS: Da dies eine Hausaufgabe sein kann, gebe ich Ihnen nicht die genaue Lösung, aber geben Sie eine Vorstellung von dem Problem. Beim nächsten Mal verwende bitte Englisch als Benennungsschema. Dies hilft Leuten, Ihren Code zu debuggen.

      #include <stdio.h> 
      
      #include <unistd.h> 
      #include <stdlib.h> 
      
      
      int main(void) 
      { 
      int msg; 
      int child_pid; 
      int parent_to_child[2]; 
      int child_to_parent[2]; 
      
      
      
      // my_pipe 
      int ret_val = pipe(parent_to_child); 
      if(ret_val!=0){ 
          printf("pipe command failed !!\n"); 
          exit(1); 
      } 
      
      // my_lock 
      ret_val = pipe(child_to_parent); 
      if(ret_val!=0){ 
          printf("pipe command failed !!\n"); 
          exit(1); 
      } 
      
      child_pid = fork(); 
      if(child_pid==-1){ 
      
          printf("fork() failed !!\n"); 
          exit(1); 
      
      }else if(child_pid==0){ 
      
          // i am child 
          read(parent_to_child[0], &msg, sizeof(int)); 
          printf("child got %d from parent \n", msg); 
          msg = 34; 
          write(child_to_parent[1], &msg, sizeof(int)); 
      
      }else{ 
      
          // i am parent 
          msg = 24; 
          write(parent_to_child[1], &msg, sizeof(int)); 
          //sleep(2); 
          read(child_to_parent[0], &msg, sizeof(int)); 
          printf("parent got %d from child \n", msg); 
      
      } 
      
      return 0; 
      } 
      
    Verwandte Themen