2017-12-12 8 views
0

Das Ziel meines Programms ist es, zwei Pipes und zwei Prozesse zu erstellen, die sich gegenseitig lesen und schreiben auf die Pipes.Pipe() und fork()

  1. Prozess P1 liest aus Rohr c1 und schreibt in das Rohr c2
  2. Prozess P2 liest aus Rohr c2 und schreibt in das Rohr c1

bis die Lesenummer aus dem Rohr weniger als BIG_INT_STOP Die beiden Prozesse erhöhen weiterhin die Anzahl der Rohre. Sobald diese Bedingung zutrifft, wird zuerst der Prozess gelesen, die Pipes geschlossen, die Pipes geschlossen und die Nummer ausgedruckt. Das Problem ist: Wenn der Prozess p2 vor p1 endet und wenn der Prozess p1 vor p2 endet, geht er in die Schleife. Können Sie mir erklären warum?

#include <stdio.h> 
#include <stdlib.h> 
#include <unistd.h> 
#include <sys/sysinfo.h> 
#include <sys/wait.h> 
#include <errno.h> 
#include <time.h> 
#include <string.h> 
#define BIG_INT_STOP 40 
#define TEST_ERROR if (errno) {fprintf(stderr, \ 
        "%s:%d: PID=%5d: Error %d (%s)\n", \ 
        __FILE__,   \ 
        __LINE__,   \ 
        getpid(),   \ 
        errno,   \ 
        strerror(errno));} 

int main(){ 
    int c1[2], c2[2], p1, p2, z; 
    long a = 0, c; 
    pipe(c1); 
    pipe(c2); 
    write(c1[1], &a, sizeof(a)); 
    write(c2[1], &a, sizeof(a)); 
    p1 = fork(); 
    p2 = fork(); 
    switch(p1){ 
    case -1: 
     TEST_ERROR; 
     exit(EXIT_FAILURE); 
    case 0: 
     read(c1[0], &c, sizeof(c)); 
     while(c != BIG_INT_STOP){ 
     ++c; 
     write(c2[1], &c, sizeof(c)); 
     read(c1[0], &c, sizeof(c)); 
     } 
     close(c1[0]); 
     close(c1[1]); 
     close(c2[0]); 
     close(c2[1]); 
     printf("p1: %ld\n", c); 
     exit(0); 
    } 
    switch(p2){ 
    case -1: 
     TEST_ERROR; 
     exit(EXIT_FAILURE); 
    case 0: 
     read(c2[0], &c, sizeof(c)); 
     while(c != BIG_INT_STOP){ 
     ++c; 
     write(c1[1], &c, sizeof(c)); 
     read(c2[0], &c, sizeof(c)); 
     } 
     close(c1[0]); 
     close(c1[1]); 
     close(c2[0]); 
     close(c2[1]); 
     printf("p2: %ld\n", c); 
     exit(0); 
    } 
    while(wait(&z) != -1); 
} 
+0

Vielleicht, weil Sie nicht die Ergebnisse von 'write' und' read' für geschriebene Bytes und/oder Fehlercodes überprüfen? – Marian

+0

Zwei Prozesse drucken immer ihre Nummer am Ende der Ausführung meines Programms, warum sollte es einen Fehler geben? – Lorenzo

Antwort

3

Ihr Programm ist ein bisschen seltsam. Das Hauptproblem scheint zu sein, dass der zweite Fork sowohl im Hauptprogramm als auch im ersten Kind ausgeführt wird. In der Tat laufen Sie vier Prozesse: Haupt, zwei Söhne von Haupt und der Sohn des ersten Sohnes. Dies ist wahrscheinlich nicht das, was Sie wollen. Sie wollten wahrscheinlich die erste switch direkt nach der ersten fork setzen und die zweite fork nur im Hauptprogramm ausführen.

Und natürlich überprüfen Sie nicht die Ergebniswerte read und write für unerwartete Situationen.

1

Problem ist p2 ist 2 mal gegabelten. Einmal im Elternprozess und zum zweiten Mal in p1-Prozess.

Statt:

p1 = fork(); 
    p2 = fork(); 

müssen Sie wie folgt schreiben:

p1 = fork(); 
if (p1 > 0) { 
     p2 = fork(); 
} 
0

Ihr Code nicht richtig Fehler macht auf die Anrufe zu read und write Überprüfung, was bedeutet, dass, wenn es Wenn ein Problem beim Lesen der Pipes auftritt, tritt das Kind in eine nie endende Schleife ein, da der Wert c niemals den Beendigungswert erreicht.

Da Ihre Kindprozesse die Rohre schließen, wenn sie fertig sind, haben Sie eine sehr hohe Wahrscheinlichkeit, in einen Race Condition zu gelangen, in dem ein Prozess die Rohre schließt, bevor der andere den letzten Wert von c einliest. Dies wird durch die Platzierung Ihrer Anrufe fork compoundiert wie Sie derzeit mit 3 Kindprozesse am Ende nicht 2.

Sie sollten den zweiten Anruf fork nach dem switch bewegen, wie Sie wissen, dass Sie nur an diesem Punkt sein kann, in den übergeordneten Prozess und verschieben Sie auch das Schließen der Pipes an den übergeordneten.

+0

vielen Dank, aber so muss ich für jedes Auftreten eines "schreiben" oder "lesen" eine Kontrolle durchführen? – Lorenzo

+0

In diesem Fall, definitiv, da, was Sie einlesen, ist direkt mit dem, was Ihre while-Schleife steuert. –