2013-05-24 15 views
8

Ich habe ein Programm, das eine Zufallszahl erzeugt, n, dann Schleifen n mal.In der Reihenfolge der Beendigung drucken?

Bei jeder Iteration wird der Wert sleeptime zufällig ausgewählt und verzweigt. Der untergeordnete Prozess ruht für sleeptime Sekunden und endet dann mit dem Wert der Indexvariablen.

Das übergeordnete Element wird dann erneut durchlaufen und wartet darauf, dass jeder Prozess beendet wird. Wenn jeder Prozess beendet wird, versuche ich, die PID und die childid des Prozesses auszulöschen, aber da stoße ich in Schwierigkeiten. Die PIDs werden der Reihe nach gedruckt, und childid bleibt bei 0.

Was mache ich falsch?

int main(int argc, char* argv[]) 
{ 

    // Wire up the timer 
    long time = elapsedTime(0); 

    /* Generate a random number between MINFORKS and MAXFORKS 
    */ 
    unsigned int seed = generateSeed(0); 
    int n = rand_r(&seed) % MAXFORKS + MINFORKS-1; 

    /* Log next step 
    */ 
    time = elapsedTime(1); 
    printf("%li: Number of forks = %i\n", time, n); 

    /* Hang on to the PIDs so we can wait for them after forking 
    */ 
    pid_t *PIDs = (pid_t *)(malloc(sizeof(*PIDs)*n)); 


    /* Fork n times 
    */ 
    for (int i = 0; i < n ; i++) 
    { 
     /* Call fork() and retain the returned identifier 
     */ 
     pid_t processIdentifier = fork(); 

     /* Randomize the child sleep time 
     */ 
     seed = generateSeed(0); 
     int sleeptime = rand_r(&seed) % MAXPAUSE + MINPAUSE; 

     /* Check for errors 
     */ 
     if (processIdentifier == -1) { 
      printf("Error: %i", errno); 
     } 


     if (!processIdentifier) 
     { 
      /* We're in the child process, 
      * sleep and then exit with 
      * i as the error code. 
      */ 

      usleep(sleeptime); 
      _exit(i); 
     } 
     else 
     { 
      /* We're in the parent: 
      * Store the PID and 
      * print out the results. 
      */ 

      PIDs[i] = processIdentifier; 

      time = elapsedTime(1); 
      printf("%li: Child %i, pid = %i, forked, waits %i usec\n", time, i, processIdentifier, sleeptime); 

     } 
    } 

    /* Log next step 
    */ 
    time = elapsedTime(1); 
    printf("%li: Finished forking, going to wait.\n", time); 

    /* 
    * Loop through the processes and wait for them 
    * to terminate. Then print the childid, and the 
    * the pid. 
    */ 

    for (int i = 0; i < n; i++) 
    { 

     /* Get the PID we want to track 
     */ 
     pid_t pid = PIDs[i]; 

     /* Wait for the child process 
     * and grab it's status info 
     */ 
     int status = NULL; 


     waitpid(pid, &status, 0); 

     int childid = -1; 
     if(WIFEXITED(status)) 
     { 
      childid = WTERMSIG(status); 
     } 

     /* Log the results 
     */ 
     time = elapsedTime(1); 
     printf("%li: Child %i, pid = %i, terminated\n", time, childid, pid); 
    } 

    /* All done! 
    */ 
    time = elapsedTime(1); 
    printf("All done. It only took %li milliseconds!", time); 
} 

Haftungsausschluss ist diese Hausaufgaben (link here, may disappear at any time), aber ich habe schon fast alle es getan. Ich habe nur Schwierigkeiten, diesen einen Aspekt zu begreifen.

Antwort

4

Ihr Code wartet auf die PIDs in der Reihenfolge, in der Sie sie in Ihren aufeinanderfolgenden Aufrufen waitpid() bereitstellen. Wenn Sie stattdessen -1 als ersten Parameter an waitpid() übergeben (oder wenn Sie einfach wait() aufrufen), erhalten Sie das erste Kind, über das der Kernel Sie informiert, und nicht das, über das Sie speziell benachrichtigt wurden. Überprüfen Sie den Rückgabewert, um zu sehen, welches Kind es war (oder ob ein Fehler aufgetreten ist).

Die childid bleibt 0, weil Sie sind WTERMSIG aus dem Wartezustand zu extrahieren, anstatt WEXITSTATUS.

2

Zuerst wartet es, bis der erste Prozess beendet wird, und druckt dann die Informationen aus diesem Prozess.
Dann wartet es darauf, dass der zweite Prozess beendet wird, und druckt dann die Informationen aus diesem Prozess.
Dann wartet es auf den dritten Prozess zu beenden ...

Und Sie fragen sich, warum sie in der Reihenfolge gemeldet werden?

Pass -1 bis waitpid statt, die this page sagt, wird dazu führen, dass für jeden Kind Thread statt bestimmten Thread zu warten.

Auch direkt vor dem Drucken haben Sie int childid = -1;. Nicht sicher warum.

Verwandte Themen