Visualizzazione dei risultati da 1 a 8 su 8
  1. #1
    Utente bannato
    Registrato dal
    Apr 2009
    Messaggi
    30

    Qualcuno mi puo chiarire un dubbio su questo esercizio di pthreads??

    Ciao a Tutti, ho fatto questo esercizio con 2 processi e 2 threads in esecuzione, pero ho un piccolo dubbio..
    posto il codice e poi mi chiarirò

    #include<stdio.h>
    #include<unistd.h>
    #include<signal.h>

    #define SIZE 5

    /*
    *
    questo programma manda in esecuzione 2 processi e ciascuno di loro richiama un thread
    differente per riempire un array e azzerarlo successivamente
    *
    */

    int array[5];
    int *pt = &array[0];

    int *increment_values(int *pt)
    {
    int i;
    for(i=0;i<SIZE;i++)
    {
    (*pt++) = (i*50);
    printf("array[%d] = %d\n", i, array[i]);
    }
    pthread_exit(0);
    }

    int *to_0_values(int *pt)
    {
    int i;
    for(i=0;i<SIZE;i++)
    {
    (*pt++) = 0;
    printf("array[%d] = %d\n", i, array[i]);
    }
    }


    void producer()
    {
    int i;
    pthread_t tp;
    pthread_attr_t attr_tp;

    printf("Thread Producer increments values in Buffer\n");
    pthread_attr_init(&attr_tp);
    pthread_create(&tp, &attr_tp, &increment_values, &array);
    pthread_join(tp, 0);

    }

    void consumer()
    {
    int i;
    pthread_t tc;
    pthread_attr_t attr_tc;

    printf("Thread Consumer removes values from Buffer\n");
    pthread_attr_init(&attr_tc);
    pthread_create(&tc, &attr_tc, &to_0_values, &array);
    pthread_join(tc, 0);

    pthread_exit(0);
    }

    main()
    {
    int i;
    pid_t p;
    printf("\n**Main Process %d calling thread for function \"producer();\"\n", (int)getpid());
    producer();

    p = fork();

    if(p==0)
    {
    printf("\n\n**Son Process %d calling thread for function \"consumer();\"\n", p);
    consumer();
    kill(p, 0);
    }
    printf("\nProcess & Threads successfully complets\n");
    }

    e questo è l'output:

    Thread Producer increments values in Buffer
    array[0] = 0
    array[1] = 50
    array[2] = 100
    array[3] = 150
    array[4] = 200


    **Son Process 0 calling thread for function "consumer();"
    Thread Consumer removes values from Buffer
    array[0] = 0
    array[1] = 0
    array[2] = 0
    array[3] = 0
    array[4] = 0

    Process & Threads successfully complets

    Tutto sembra corretto, ma se le istruzioni di stampa per l'array io le sposto in main invece che lasciarle nelle 2 funzioni increment_values & to_0_values, quindi il main diviene cosi;

    main()
    {
    int i;
    pid_t p;
    printf("\n**Main Process %d calling thread for function \"producer();\"\n", (int)getpid());
    producer();

    for(i=0;i<SIZE;i++)
    printf("array[%d] = %d\n", i, array[i]);

    p = fork();

    if(p==0)
    {
    printf("\n\n**Son Process %d calling thread for function \"consumer();\"\n", p);
    consumer();
    for(i=0;i<SIZE;i++)
    printf("array[%d] = %d\n", i, array[i]);
    kill(p, 0);
    }
    for(i=0;i<SIZE;i++)
    printf("array[%d] = %d\n", i, array[i]);

    printf("\nProcess & Threads successfully complets\n");
    }

    perche l'output e' scorretto?

    **Main Process 7360 calling thread for function "producer();"
    Thread Producer increments values in Buffer
    array[0] = 0
    array[1] = 50
    array[2] = 100
    array[3] = 150
    array[4] = 200


    **Son Process 0 calling thread for function "consumer();"
    Thread Consumer removes values from Buffer
    array[0] = 0
    array[1] = 50
    array[2] = 100
    array[3] = 150
    array[4] = 200

    Process & Threads successfully complets

    Non capisco perche in teoria le 2 funzioni increment_values & to_0_values dovrebbero modificare i dati degli array.. Qualcuno mi po aiutare a chiarire questo dubbio? MAgari l'esercizio al principio della discussione e' sbagliato per qualche motivo di cui non mi sono reso conto, se qualcuno che ne sa piu di me mi puo chiarire le idee mi farebbe piacere.. Grazie mille!

  2. #2
    Utente di HTML.it
    Registrato dal
    Jul 2008
    Messaggi
    1,326
    Ancora prima di capire cos'è che non va e perché non va, direi di rivedere un po' il codice... innanzitutto la prossima volta postalo tra tag "code" come è scritto nel regolamento che andrebbe letto prima di postare... non è solo una regola, è un fatto di convenienza perché come vedi il codice postato così è illeggibile.

    Inoltre, se compili il codice così

    codice:
    $ gcc codice.c -o codice -Wall -pedantic -lpthread
    ottieni

    codice:
    codice.c: In function 'increment_values':
    codice.c:24: warning: implicit declaration of function 'pthread_exit'
    codice.c:25: warning: control reaches end of non-void function
    codice.c: In function 'to_0_values':
    codice.c:34: warning: control reaches end of non-void function
    codice.c: In function 'producer':
    codice.c:44: warning: implicit declaration of function 'pthread_attr_init'
    codice.c:45: warning: implicit declaration of function 'pthread_create'
    codice.c:46: warning: implicit declaration of function 'pthread_join'
    codice.c:39: warning: unused variable 'i'
    codice.c: In function 'consumer':
    codice.c:52: warning: unused variable 'i'
    codice.c: At top level:
    codice.c:65: warning: return type defaults to 'int'
    codice.c: In function 'main':
    codice.c:66: warning: unused variable 'i'
    codice.c:83: warning: control reaches end of non-void function
    quindi direi di includere l'header file <pthread.h>

    Fatto questo, ricompilando con la stessa opzione ottieni ancora

    codice:
    codice.c: In function 'to_0_values':
    codice.c:35: warning: control reaches end of non-void function
    codice.c: In function 'producer':
    codice.c:46: warning: passing argument 3 of 'pthread_create' from incompatible pointer type
    codice.c:40: warning: unused variable 'i'
    codice.c: In function 'consumer':
    codice.c:59: warning: passing argument 3 of 'pthread_create' from incompatible pointer type
    codice.c:53: warning: unused variable 'i'
    codice.c: At top level:
    codice.c:66: warning: return type defaults to 'int'
    codice.c: In function 'main':
    codice.c:67: warning: unused variable 'i'
    codice.c:84: warning: control reaches end of non-void function
    Il che significa che sbagli a richiamare la pthread_create (a parte il resto). Il prototipo della funzione è

    codice:
    int pthread_create(pthread_t *restrict thread,
                  const pthread_attr_t *restrict attr,
                  void *(*start_routine)(void*), void *restrict arg);
    come vedi il terzo argomento è un puntatore ad una funzione che restituisce un puntatore di tipo void e riceve come argomento sempre un puntatore di tipo void, ma sia increment_values() che to_0_values() sono dichiarate diversamente... inoltre, quando si passa un puntatore a funzione non c'è bisogno dell'operatore &, anzi è proprio sbagliato: il nome di una funzione di per sé è già un puntatore, proprio come un array.

    Comincia a correggere questo, posta il codice corretto (con i tag "code") e poi si vede...
    every day above ground is a good one

  3. #3
    Utente bannato
    Registrato dal
    Apr 2009
    Messaggi
    30

    RE: Sembrerebbe risolto.

    Ok, sembra che ho risolto il problema aggiustando un po il codice...ho dichiarato le funzioni a void senza argomenti.

    **GRAZIE PER IL SUGGERIMENTO DI COMPILAZIONE, NON LO CONOSCEVO, mi mancava un "man gcc" ** ora la compilazione non da errori...

    Ho cambiato un po il codice, dovrebbe essere un po piu chiaro in piu ho riportato i commenti, spero si abbastanza comprensibile...

    codice:
    #include<stdio.h>
    #include<unistd.h>
    #include<signal.h>
    #include<pthread.h>
    
    #define SIZE 5
    
    /*
     *
     questo programma manda in esecuzione 2 processi e ciascuno di loro richiama un thread 
     differente per riempire un array e azzerarlo successivamente
     *
     */
     
    int array[5];
    int *pt = &array[0];
    
    void *increment_values()                    //funzione per incrementare i valori nell'array...
    { 
     int i;
     
     for(i=0;i<SIZE;i++)
     {
      (*pt++) = (i*50); //incrementa ..
      printf("array[%d] = %d\n", i, array[i]);  //stampa array..
     }
    
     return &pt; 
     pthread_exit(0);                                //stop current thread.
    }
    
    void *to_0_values()                           //funzione per azzerare nuovamente i valori.
    {
     int i;
    
     for(i=SIZE;i>0;i--)
     { 
      (*pt--) = 0; // azzera tutto l'array
      printf("array[%d] = %d\n", i, array[i]);  //stampa array..
     }
     return &pt;
     pthread_exit(0); //stop current thread..
    }
    
    void increment_thread()                     //funzione che crea il thread per increment_value()
    {
     pthread_t tp;
     pthread_attr_t attr_tp;
    
     printf("## 1st Thread increments values in Array ##\n");
     pthread_attr_init(&attr_tp);
              
     //create thread.. 
     pthread_create(&tp, &attr_tp, increment_values, NULL);
     pthread_kill(tp, o)
    }
    
    void to_0_threadr() //funzione che crea il thread per to_0_value()
    {
     pthread_t tc;
     pthread_attr_t attr_tc;
    
     printf("## 2nd Thread removes values from Array ##\n");
     pthread_attr_init(&attr_tc);
     pthread_create(&tc, &attr_tc, to_0_values, NULL); // crea il thread
     pthread_kill(tc, o)
    }
    
    int main()
    {
     pid_t p1,p2; //processi;
     p1 = getpid(); //incomincia primo processo
    
     if(p1>0) 
     {
      printf("\n**Main Process %d calling thread for function \"increment_thread();\"\n", p1);
      increment_thread(); //processo chiama il thread
     }
    
     p2 = fork();
     
     if(p2==0)
     {
      printf("\n\n**Son Process %d calling thread for function \"to_0_thread()\"\n", p2);
      to_0_thread(); //processo chiama il thread
    
      pthread_exit(0); // qui richiamo la funzione senno il programma resta in block... da chiarire
     }
    
     printf("\nProcess & Threads successfully complets\n");
     return 0;
    }
    Tra l'altro ho trovato questa pagina sul Posix Thread Programming a questo indirizzo..

    https://computing.llnl.gov/tutorials/pthreads/

    gia stampata in PDF..

    Accetto commenti buoni e brutti, Ringrazio in anticipo su tutto..

    YuYevon, dopo i tuoi insegnamenti mi piacerebbe conoscere un tuo giudizio sulla soluzione..

  4. #4
    Utente bannato
    Registrato dal
    Apr 2009
    Messaggi
    30

    ORA È RISOLTO, ANCHE SE HO OPTATO PER UN SOLO PROCESSO DI ESECUZIONE * 2 THREAD..

    Volevo cancellare il messaggio di prima ma mi e' poi scaduto il tempo dei 60 minuti e dovrei contattare l'amministratore per modificarlo... nooo... cmq era scorretto..

    Chissà che il tentativo di 2 processi era una task ancora complicata per me..
    Diciamo che c'era abbastanza confusione creata dall'esecuzione di questi ultimi. Probabilmente un implentazione di quel genere richiedeva qualche tecnica differente come un semaforo, ma per quello ancora devo migliorare un po...

    Posto il codice corretto

    codice:
    #include<stdio.h>
    #include<unistd.h>
    #include<signal.h>
    #include<pthread.h>
    
     
    int array[5];
    int *pt = &array[0];
    
    void *increment_values()
    { 
     int i;
     for(i=0;i<5;i++)
      (*pt++) = (i*50);
     return &pt;
     pthread_exit(0);
    }
    
    void *to_0_values()
    {
     int i;
     for(i=4;i>=0;i--)
      (*pt--) = 0;
     return &pt;
     pthread_exit(0);
    }
    
    void increment_thread()
    {
     pthread_t tp;
     pthread_attr_t attr_tp;
    
     printf("\n## 1st Thread increments values in Array ##\n");
     pthread_attr_init(&attr_tp);
     pthread_create(&tp, &attr_tp, increment_values, NULL);
    }
    
    void to_0_thread()
    {
     pthread_t tc;
     pthread_attr_t attr_tc;
    
     printf("\n## 2nd Thread removes values from Array ##\n");
     pthread_attr_init(&attr_tc);
     pthread_create(&tc, &attr_tc, to_0_values, NULL);
    }
    
    int main()
    {
     int i;
     pid_t p = getpid();
    
     if(p<0)
     { 
      fprintf(stderr, "Error generating Process\n");
      return 1;
     }
     else
     {
      printf("\n**Process %d calls 1st Thread for function \"increment_thread()\" wich calls function \"increment_values()\"\n",p);
      increment_thread();
    
      for(i=0;i<5;i++)
      printf("array[%d] = %d\n", i, array[i]);
    
      printf("\n**Process %d now is calling 2nd Thread for function \"to_0_thread()\" wich calls function \"to_0_values()\"\n", p);
      to_0_thread();
    
      for(i=0;i<5;i++)
      printf("array[%d] = %d\n", i, array[i]);
    
      printf("\nProcess & Threads successfully complets\n\n");
     } 
     return 0; 
    }
    Output...

    codice:
    **Process 15324 calls 1st Thread for function "increment_thread()" wich calls function "increment_values()"
    
    ## 1st Thread increments values in Array ##
    array[0] = 0
    array[1] = 50
    array[2] = 100
    array[3] = 150
    array[4] = 200
    
    **Process 15324 now is calling 2nd Thread for function "to_0_thread()" wich calls function "to_0_values()"
    
    ## 2nd Thread removes values from Array ##
    array[0] = 0
    array[1] = 0
    array[2] = 0
    array[3] = 0
    array[4] = 0
    
    Process & Threads successfully complets
    Ancora una volta con qualche piccolo sforzo i miei "esperimenti" funzionano.. cmq io volevo fare il tutto con 2 processi ...

    Accetto volentieri suggerimenti a riguardo..

    Ciao Grazie!!

  5. #5
    Utente di HTML.it
    Registrato dal
    Jul 2008
    Messaggi
    1,326
    Per quanto riguarda l'ultimo codice che hai postato, anche se funziona ci sono un paio di cose che non mi convincono.

    Innanzitutto, perché scrivi questo

    codice:
    pid_t p = getpid();
    
     if(p<0)
     { 
      fprintf(stderr, "Error generating Process\n");
      return 1;
     }
    ?

    Un controllo sul pid del processo ha senso solo dopo una fork(), ma non dopo una getpid()... la getpid() restituisce il PID del processo corrente, ma questo non potrebbe mai essere minore di 0... se il programma è in esecuzione, significa che il sistema operativo ha creato con successo il processo e che questo è stato schedulato senza problemi, quindi il PID del processo sicuramente esiste, tra l'altro la getpid() è scritta in maniera tale da non poter mai fallire

    man 2 getpid
    NAME
    getpid, getppid - get process identification
    ...
    ...
    ERRORS
    These functions are always successful.
    Quindi direi che quel controllo può essere tranquillamente eliminato... magari specifica meglio cosa intendessi fare (lavorare con due processi? Anche perché nel messaggio di errore scrivi "Error generating process"... getpid() non crea un processo).

    Per il resto nulla da dire... se non che quando usi il tipo pid_t (che come dicevo in questo caso è inutile) dovresti includere l'header file <sys/types.h>. Il compilatore in questo caso non si lagna evidentemente perché l'header è incluso già all'interno degli altri header file che hai incluso tu, ma in generale per una questione di pulizia sarebbe meglio farlo esplicitamente...

    Per quanto riguarda il penultimo codice invece non ho capito cosa intendevi fare... tra l'altro ottengo ancora errori e warnings in compilazione

    codice:
    codice.c:18:45: warning: C++ style comments are not allowed in ISO C90
    codice.c:18:45: warning: (this will be reported only once per input file)
    codice.c: In function 'increment_thread':
    codice.c:55: error: 'o' undeclared (first use in this function)
    codice.c:55: error: (Each undeclared identifier is reported only once
    codice.c:55: error: for each function it appears in.)
    codice.c:56: error: expected ';' before '}' token
    codice.c: In function 'to_0_threadr':
    codice.c:66: error: 'o' undeclared (first use in this function)
    codice.c:67: error: expected ';' before '}' token
    codice.c: In function 'main':
    codice.c:85: warning: implicit declaration of function 'to_0_thread'

    Ah un consiglio per indentare

    codice:
    indent -kr nome_sorgente.c
    così il codice è indentato secondo lo stile Kernighan and Ritchie, tra l'altro indent ha così tante opzioni che ti consente di indentare il codice come meglio credi ;D
    every day above ground is a good one

  6. #6
    Utente bannato
    Registrato dal
    Apr 2009
    Messaggi
    30

    RE:

    Ah no lascia perdere il penultimo.. il codice poi l'ho cambiato piu di un paio di volte quindi non ci fare proprio caso, l'esercizio che funziona e' l'ultimo...

    Per il getpid() si in effetti non ha molto senso, ma dovevo pigiare i tasti e alle 6 di mattina dopo uno studio di threads, scheduling & deadlocks ed in piu riprendere un esercizio lasciato indietro qualche err non puo mancare , l'importante e' imparare dagli errori come faccio quando capita.. cmq.. nn l'avevo notata la chicca di indent.. e comunque non mi piace quello stile, mi confondono le graffe tipo stile ;

    codice:
     if (expr) {
    
      istruzione
     
     }
    
     preferisco
    
     if (expr)
     {
    
      istruzione
     
     }
    Grazie ancora di tutto per i consigli.. Alla prossima discussione!

  7. #7
    Utente di HTML.it L'avatar di Stoicenko
    Registrato dal
    Feb 2004
    Messaggi
    2,254
    basta cambiare parametro..

  8. #8
    Utente bannato
    Registrato dal
    Apr 2009
    Messaggi
    30

    ??

    Ah ok il parametro di indent... ma si non e' che mi devo fare i problemi con una tool per indentare il codice... lo faccio da me...quando avro tempo ci daro un¡occhiata

    Ahah

Permessi di invio

  • Non puoi inserire discussioni
  • Non puoi inserire repliche
  • Non puoi inserire allegati
  • Non puoi modificare i tuoi messaggi
  •  
Powered by vBulletin® Version 4.2.1
Copyright © 2024 vBulletin Solutions, Inc. All rights reserved.