Newsgroup: it.comp.os.linux.development
Titolo: Problemi con rand e processi multipli.

Facendo girare questo snip di codice:
  srand(time(NULL));
  for (int i = 0; i < n_router-1; i++) {
    offset_time = (int) rand () % 10;
    pid = fork ();
    if (pid == 0) break;
    /* else if (pid < 0) return (-1); << non necessario */
    id++;
  }
  simularouter(id, offset_time);
l'idea e' assegnare un valore intero ad ogni nuovo processo da usare
come offset temporale, il problema e' che a parte il primo processo
creato, gli altri invocano la funzione simularouter tutti con lo
stesso offset_time... perche'?
grazie per l'attenzione.
-- 
Elwood (Peter S.)

 stesso offset_time... perche'?
#include <stdlib.h>
#include <time.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#ifndef NROUTER
# define NROUTER 10
#endif
void
simularouter(int id,int offset_time)
{
    printf("id= %05d offset_time=%1d \n",id,offset_time);
}
int main(void)
{
    srand(time(NULL));
    for (int i = 0; i != NROUTER ; ++i)
    {
        int offset_time = (int) (10.0*rand()/(RAND_MAX+1.0));
        pid_t pid = fork();
        #define IS_IN_CHILD(a) ((a)==0)
        if (IS_IN_CHILD(pid) )
        {
            simularouter(i,offset_time);
            exit(EXIT_SUCCESS);
        }
        #undef IS_IN_CHILD
    }
    for(int i=0; i != NROUTER ; ++i)
    {
        int status;
        wait(&status);
    }
    return 0;
}
sbirish@sophia sbirish $ gcc -o crapc crap.c -std=c99 && ./crapc
id= 00000 offset_time=9
id= 00001 offset_time=2
id= 00002 offset_time=1
id= 00003 offset_time=5
id= 00004 offset_time=3
id= 00005 offset_time=7
id= 00006 offset_time=8
id= 00007 offset_time=7
id= 00008 offset_time=4
id= 00009 offset_time=9
sbirish@sophia sbirish $

anch'io ho fatto dei programmi di questo tipo per un esame e avevo lo
stesso problema.
penso sia perché il generatore dei numeri casuali viene inizializzato dal
processo padre e quindi i figli generaro tutti gli stessi numeri.
volevo provare a mettere la srand(time(0)) dopo la fork(), ma ho sempre
rimandato.
ciao
-- 
     _
    | |
 ___| |	
http://magicforum.altervista.org
(    .'
 )  (

 [CUT]
Credo bastasse indicare come soluzione o l'opzione A = "metti rand() prima
della fork()" (come hai fatto tu) o l'opzione B = "metti srand() con il
pid dopo la fork" (non con time(NULL) che ritornerebbe comunque lo stesso
valore per tutti i figli) anziché scrivere tutto il codice :)
Tuttavia, visto che l'hai fatto, rispondo a te giusto per segnalarti che
è piu corretto uscire da un processo figlio con la chiamata _exit()
piuttosto che exit().
Ciau
Matic

 piuttosto che exit().
visto che hai tutto il codice, spiegami anche quali sono, in quel codice,
le impllicazioni dell'uso di exit() invece di _exit()
-- 
sbirish



l'implicazione sta nel fatto che tu non sai che cosa ne vuole fare
della sua fork() Elwood, quindi è _piu_corretto_ dirgli che da un
processo figlio si esce con _exit() piuttosto che con exit().
Cia`

 figlio si esce con _exit() piuttosto che con exit().
quale parte di "in quel codice" non hai capito?
sottolineo tra l'altro, deve anche esserti sfuggito che anche lui
usa rand prima di forkare, che usa un modo "considerato scorretto" di dare
un range a rand(), che quando forka anche il parent esegue la funzione
(che dubitavo fosse voluto, se non per altro, perché non tiene traccia di
quale sia il parent ed i child, e non ha modo quindi di waitare sui child).
credevo fosse un motivo sufficiente per sporcare il ng con 10 righe di
codice per un esempio.
è palese che in quel codice l'uso di exit() invece di _exit() non muove
alcuna problematica, visto che non sono registrati signal handler nè
tantomeno ci sono funzioni registrate con atexit, non vengono usati file
temporanei.
sbirish.

 temporanei.
quindi se uno ti posta un pezzo di codice di esempio come il seguente
int main()
{
  char * stringa = "Hello world\n";
  printf( stringa );
  return 0;
}
tu non dici niente perché l'uso di printf in questo frangente non muove
alcuna problematica ? Vabbč, mi fermo qui perché stiamo sfociando
nell'ot piů insensato.
Saluti
Matiz

     srand(time(NULL));
Adesso mi funziona, grazie.
-- 
Elwood (peter s.)