2013-05-24 18 views
8

Ho un programma che genera un numero casuale, n, quindi loop n volte.Stampa in ordine di terminazione?

Su ogni iterazione, randomizza il valore di sleeptime e chiama fork. Il processo figlio dorme per sleeptime secondi, quindi esce con il valore della variabile indice.

Il genitore quindi esegue di nuovo il ciclo, in attesa che ciascun processo venga terminato. Alla fine di ogni processo, sto cercando di disconnettere il pid e il childid del processo, ma è qui che mi trovo nei guai. I pids stanno stampando in ordine e childid rimane a 0.

Cosa sto facendo male?

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); 
} 

di responsabilità, questo è compito (link here, may disappear at any time), ma ho già fatto quasi tutto. Sto solo avendo difficoltà a cogliere questo aspetto.

risposta

4

Il tuo codice è in attesa sui pidi nell'ordine in cui li stai fornendo nelle tue successive chiamate waitpid(). Se si passa -1 come primo parametro a waitpid() (o se si chiama semplicemente wait()), si otterrà il primo figlio del quale il kernel informa, piuttosto che quello a cui si è specificamente richiesto di essere informato. Controlla il valore restituito per vedere quale bambino era (o se si è verificato un errore).

Il childid rimane 0 perché si sta estraendo WTERMSIG dallo stato di attesa, piuttosto che WEXITSTATUS.

2
for (int i = 0; i < n; i++) 
{ 
    pid_t pid = PIDs[i]; 
    int status = NULL; 
    waitpid(pid, &status, 0); 

Quindi, prima attende il completamento del primo processo, quindi stampa le informazioni da quel processo.
Quindi attende il termine del secondo processo, quindi stampa le informazioni da quel processo.
Quindi attende il termine del terzo processo ...

E ti stai chiedendo perché vengono segnalati in ordine?

passaggio -1 a waitpid invece, che this page dice farà sì che aspettare qualsiasi discussione bambino invece di thread specifico.

Inoltre, subito prima della stampa, si dispone di int childid = -1;. Non so perché.